home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / SamplePart (C) / Source / SamplePart.c < prev    next >
Encoding:
Text File  |  1995-12-08  |  136.9 KB  |  4,629 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.  
  3.     File:            SamplePart.c
  4.     
  5.     Written by:        Steve Smith and Andrey Dolgachev
  6.     
  7.     Copyright:        © 1995 by Apple Computer, Inc., all rights reserved.
  8.     
  9.     Description:    SamplePart demonstrates the most basic functions and
  10.                     responsibilities of an OpenDoc™ leaf part.
  11.     
  12.     
  13.     Demonstrates:    The following recipes were used in implementing the
  14.                     SamplePart:
  15.                      1. Open
  16.                      2. Adding A Display Frame
  17.                      3. Adding A Facet
  18.                      4. Part Drawing
  19.                      5. Refcounting Geometry
  20.                      6. ViewTypes & Presentations
  21.                      7. Display Frame 'ternalization
  22.                      8. Part Init & Externalization
  23.                      9. Part Init & partWrapper
  24.                     10. Part Storage Model
  25.                     11. Persistent Reference
  26.                     12. RefCounting
  27.                     13. Storage Unit
  28.                     14. Activation
  29.                     15. Basic Event Handling
  30.                     16. Menus
  31.                     17. Windows & Dialogs
  32.                     18. Exception Handling
  33.                     19. Memory Manager
  34.                     20. Using Resources
  35.     
  36.     
  37.     Notes:            
  38.     
  39.         
  40.     Known Problems:    <none>
  41.     
  42. ------------------------------------------------------------------------------*/
  43.  
  44. // Notification that this is a SOM source file 
  45. #define SampleCode_SamplePart_Class_Source
  46.  
  47. // define unscore (_) field names 
  48. #define VARIABLE_MACROS
  49.  
  50. // -- Compiler/Preprocessor Switches -- 
  51.  
  52. #ifndef _COMPILERDEFS_
  53. #include <CompDefs.h>
  54. #endif
  55.  
  56. // -- OpenDoc Utilities --
  57.  
  58. #ifndef _EXCEPT_
  59. // Exceptions define several important macros (ie. CHECKENV)
  60. // which are used in the SOM method dispatch glue. If Except.h
  61. // is not included early enough, exceptions may not be thrown
  62. // correctly when returning from a SOM method with the "ev" parameter set.
  63. #include <Except.h>
  64. #endif
  65.  
  66. // -- SamplePart Includes -- 
  67.  
  68. #ifndef _SAMPLEPARTGLOBALS_
  69. #include <SamplePartGlobals.h>
  70. #endif
  71.  
  72. #ifndef _SAMPLEPARTDEF_
  73. #include <SamplePartDef.h>
  74. #endif
  75.  
  76. #ifndef _SAMPLEPARTUTILS_
  77. #include <SamplePartUtils.h>
  78. #endif
  79.  
  80. #ifndef SOM_SampleCode_SamplePart_ih
  81. #include <SamplePart.ih>
  82. #endif
  83.  
  84. // -- OpenDoc Includes -- 
  85.  
  86. #ifndef _ODTYPES_
  87. #include <ODTypes.h>
  88. #endif
  89.  
  90. #ifndef SOM_ODPart_h
  91. #include <Part.h>
  92. #endif
  93.  
  94. #ifndef SOM_ODFacet_h
  95. #include <Facet.h>
  96. #endif
  97.  
  98. #ifndef SOM_ODFrame_h
  99. #include <Frame.h>
  100. #endif
  101.  
  102. #ifndef SOM_ODFrameFacetIterator_h
  103. #include <FrFaItr.h>
  104. #endif
  105.  
  106. #ifndef SOM_ODArbitrator_h
  107. #include <Arbitrat.h>
  108. #endif
  109.  
  110. #ifndef SOM_Module_OpenDoc_Foci_defined
  111. #include <Foci.h>
  112. #endif
  113.  
  114. #ifndef SOM_ODShape_h
  115. #include <Shape.h>
  116. #endif
  117.  
  118. #ifndef SOM_Module_OpenDoc_StdProps_defined
  119. #include <StdProps.h>
  120. #endif
  121.  
  122. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  123. #include <StdTypes.h>
  124. #endif
  125.  
  126. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  127. #include <StdDefs.h>
  128. #endif
  129.  
  130. #ifndef SOM_Module_OpenDoc_Commands_defined
  131. #include <CmdDefs.h>
  132. #endif
  133.  
  134. #ifndef SOM_ODDraft_h
  135. #include <Draft.h>
  136. #endif
  137.  
  138. #ifndef SOM_ODStorageUnit_h
  139. #include <StorageU.h>
  140. #endif
  141.  
  142. #ifndef SOM_ODStorageUnitView_h
  143. #include <SUView.h>
  144. #endif
  145.  
  146. #ifndef SOM_ODTransform_h
  147. #include <Trnsform.h>
  148. #endif
  149.  
  150. #ifndef SOM_ODFocusSet_h
  151. #include <FocusSet.h>
  152. #endif
  153.  
  154. #ifndef SOM_ODMenuBar_h
  155. #include <MenuBar.h>
  156. #endif
  157.  
  158. #ifndef SOM_ODWindow_h
  159. #include <Window.h>
  160. #endif
  161.  
  162. #ifndef SOM_ODWindowState_h
  163. #include <WinStat.h>
  164. #endif
  165.  
  166. #ifndef SOM_ODSession_h
  167. #include <ODSessn.h>
  168. #endif
  169.  
  170. #ifndef SOM_ODTypeList_h
  171. #include <TypeList.h>
  172. #endif
  173.  
  174. #ifndef SOM_ODTypeListIterator_h
  175. #include <TypLsItr.h>
  176. #endif
  177.  
  178. // -- OpenDoc Utilities -- 
  179.  
  180. #ifndef _ITEXT_
  181. #include <IText.h>
  182. #endif
  183.  
  184. #ifndef _FOCUSLIB_
  185. #include <FocusLib.h>
  186. #endif
  187.  
  188. #ifndef _USERSRCM_
  189. #include <UseRsrcM.h>
  190. #endif
  191.  
  192. #ifndef _ODMEMORY_
  193. #include <ODMemory.h>
  194. #endif
  195.  
  196. #ifndef _ISOSTR_
  197. #include <ISOStr.h>
  198. #endif
  199.  
  200. #ifndef _ODUTILS_
  201. #include <ODUtils.h>
  202. #endif
  203.  
  204. #ifndef _STDTYPIO_
  205. #include <StdTypIO.h>
  206. #endif
  207.  
  208. #ifndef _WINUTILS_
  209. #include <WinUtils.h>
  210. #endif
  211.  
  212. #ifndef _PLFMDEF_
  213. #include <PlfmDef.h>
  214. #endif
  215.  
  216. // -- Macintosh Includes -- 
  217.  
  218. #ifndef __ERRORS__
  219. //#include <Errors.h>
  220. #endif
  221.  
  222. #ifndef __RESOURCES__
  223. #include <Resources.h>
  224. #endif
  225.  
  226. #ifndef __DIALOGS__
  227. #include <Dialogs.h>
  228. #endif
  229.  
  230. #ifndef __ICONS__
  231. #include <Icons.h>
  232. #endif
  233.  
  234. #ifndef __QUICKDRAW__
  235. #include <Quickdraw.h>
  236. #endif
  237.  
  238. #ifndef __GXMATH__
  239. #include <GXMath.h>
  240. #endif
  241.  
  242. #pragma segment SamplePart
  243.  
  244.  
  245. //==============================================================================
  246. // SamplePart
  247. //==============================================================================
  248.  
  249. //------------------------------------------------------------------------------
  250. // Method:        somInit
  251. // Origin:        SOMObject
  252. //
  253. // Description:    This is the SOM equivalent of a C++ class constructor.
  254. //                In this routine, you should call your parent class's
  255. //                somInit (constructor) function and initialize your
  256. //                internal fields.
  257. //
  258. // Warnings:    You are not allowed to throw an exception from this
  259. //                method.
  260. //------------------------------------------------------------------------------
  261.  
  262. SOM_Scope    void
  263. SOMLINK        SamplePart__somInit
  264.             (
  265.                 SampleCode_SamplePart*        somSelf
  266.             )
  267. {
  268.     SampleCode_SamplePartMethodDebug("SamplePart","somInit");
  269.     
  270.     // somInit and somUninit methods behave like C++ constructors in that the
  271.     // inherited methods are called automatically.
  272.     // Thus, there is no need to call the parent class' somInit or somUninit.
  273.     
  274.     // There is also no need to set instance variables to zero/NULL
  275.     // since SOM guarantees that a newly constructed object is zeroed.
  276.  
  277.     // Lastly, it is not valid to perform any operation here which may throw
  278.     // an exception.
  279. }
  280.  
  281. //--------------------------------------------------------------------
  282. // Method:        somUninit
  283. // Origin:        SOMObject
  284. //
  285. // Description:    This is the SOM equivalent of a C++ class destructor.
  286. //                In this routine, you should clean up any internal
  287. //                fields which were not cleaned up in the ReleaseAll and
  288. //                Release methods; and finally call you parent class's
  289. //                somUninit (destructor) function.
  290. //
  291. // Warnings:    You are not allowed to throw an exception from this
  292. //                method.
  293. //--------------------------------------------------------------------
  294.  
  295. SOM_Scope    void
  296. SOMLINK        SamplePart__somUninit
  297.             (
  298.                 SampleCode_SamplePart*        somSelf
  299.             )
  300. {
  301.     SampleCode_SamplePartMethodDebug("SamplePart","somUninit");
  302. }
  303.  
  304. //==============================================================================
  305. #pragma mark    • Initialization •
  306. //==============================================================================
  307.  
  308. //------------------------------------------------------------------------------
  309. // Method:        InitPart
  310. // Origin:        ODPart
  311. //
  312. // Description:    This method is called when a new instance of this part is being
  313. //                created. The part should prepare itself to run.
  314. //
  315. // Warning:        It is not appropriate to require user iteraction while
  316. //                stationery is being created. Do not present the user with error
  317. //                dialogs or splash screens from this method.
  318. //------------------------------------------------------------------------------
  319.  
  320. SOM_Scope    void
  321. SOMLINK        SamplePart__InitPart
  322.             (
  323.                 SampleCode_SamplePart*        somSelf,
  324.                 Environment*                ev,
  325.                 ODStorageUnit*                storageUnit,
  326.                 ODPart*                        partWrapper
  327.             )
  328. {
  329.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  330.     SampleCode_SamplePartMethodDebug("SamplePart","InitPart");
  331.  
  332.     SOM_TRY
  333.         // We must call the initialize method of our parent PersistentObject
  334.         // class to generate the appropriate time/date stamp on our
  335.         // part's storage unit. 
  336.         SampleCode_SamplePart_parent_ODPart_InitPart(somSelf,ev,storageUnit,partWrapper);
  337.         CHECK_ENV(ev);
  338.     
  339.         // To allow editor swapping (translation) at runtime, OpenDoc requires
  340.         // that we pass in a "reference" to ourselves when interacting with the
  341.         // API (ie. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  342.         // The "partWrapper" passed to us here and in InitPartFromStorage is the
  343.         // "reference" OpenDoc is asking us to use.
  344.         _fSelf = partWrapper;
  345.             
  346.         // We are being created, either as part of generating stationery or
  347.         // by some editor instantiating the part, so the destination storage
  348.         // must be writeable.
  349.         _fReadOnlyStorage = kODFalse;
  350.             
  351.         // Call the common initialization code to get set up. 
  352.         _Initialize(somSelf, ev);
  353.         CHECK_ENV(ev);
  354.     
  355.         // Since we have just been created, our state/content info has
  356.         // never been written out, so setting our "dirty" flag will
  357.         // give us a chance to do that.
  358.         _SetDirty(somSelf, ev);
  359.         CHECK_ENV(ev);
  360.  
  361.     SOM_CATCH_ALL
  362.     SOM_ENDTRY
  363. }
  364.  
  365. //------------------------------------------------------------------------------
  366. // Method:        InitPartFromStorage
  367. // Origin:        ODPart
  368. //
  369. // Description:    This method is called when a document/stationery is being opened
  370. //                or when the part is internalized by its containing part. The
  371. //                part should merely read in the saved state/content and
  372. //                initialize itself. The part must not alter its storage unit;
  373. //                otherwise, the "Save" menu item becomes enabled without the user
  374. //                actually having made a change to the document.
  375. //------------------------------------------------------------------------------
  376.  
  377. SOM_Scope    void
  378. SOMLINK        SamplePart__InitPartFromStorage
  379.             (
  380.                 SampleCode_SamplePart*        somSelf,
  381.                 Environment*                ev,
  382.                 ODStorageUnit*                storageUnit,
  383.                 ODPart*                        partWrapper
  384.             )
  385. {
  386.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  387.     SampleCode_SamplePartMethodDebug("SamplePart","InitPartFromStorage");
  388.  
  389.     SOM_TRY
  390.     
  391.         // We must call the initialize method of our parent PersistentObject
  392.         // class to generate the appropriate time/date stamp on our
  393.         // part's storage unit.
  394.         SampleCode_SamplePart_parent_ODPart_InitPartFromStorage
  395.                             (somSelf,ev,storageUnit,partWrapper);
  396.         CHECK_ENV(ev);
  397.     
  398.         // To allow editor swapping (translation) at runtime, OpenDoc requires
  399.         // that we pass in a "reference" to ourselves when interacting with the
  400.         // API (ie. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  401.         // The "partWrapper" passed to us here and in InitPartFromStorage is the
  402.         // "reference" OpenDoc is asking us to use.
  403.         _fSelf = partWrapper;
  404.             
  405.         // Are we being opened from a read-only draft? If so, we cannot
  406.         // write anything back out to our storage unit.
  407.  
  408.         {
  409.             ODDraft* draft = ODGetDraftFromPart(ev,_fSelf);
  410.             _fReadOnlyStorage = ( ODDraft_GetPermissions(draft, ev) < kODDPSharedWrite );
  411.             CHECK_ENV(ev);
  412.         }
  413.                     
  414.         // Call the common initialization code to get set up. 
  415.         _Initialize(somSelf, ev);
  416.         CHECK_ENV(ev);
  417.         
  418.         // Read in the state the part was in when it was last Externalized.
  419.         // This allows the part to present the same "environment" the user
  420.         // had the part set up in the last time it was edited. 
  421.         _InternalizeStateInfo(somSelf, ev, storageUnit);
  422.         CHECK_ENV(ev);
  423.     
  424.         // Read in the contents for your part editor. 
  425.         _InternalizeContent(somSelf, ev, storageUnit);
  426.         CHECK_ENV(ev);
  427.  
  428.     SOM_CATCH_ALL
  429.     SOM_ENDTRY
  430. }
  431.  
  432. //------------------------------------------------------------------------------
  433. // Method:        Initialize
  434. // Origin:        SamplePart
  435. //
  436. // Description:    This method is called during the initialization of the part. The
  437. //                method is used to initialize all fields of the part and to
  438. //                convert ISO types to tokens for faster comparisons throughout
  439. //                the code.
  440. //------------------------------------------------------------------------------
  441.  
  442. SOM_Scope    void
  443. SOMLINK        SamplePart__Initialize
  444.             (
  445.                 SampleCode_SamplePart*        somSelf,
  446.                 Environment*                ev
  447.             )
  448. {
  449.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  450.     SampleCode_SamplePartMethodDebug("SamplePart","Initialize");
  451.  
  452.     SOM_TRY
  453.     
  454.         ODSession*        session = kODNULL;
  455.         ODArbitrator*    arbitrator = kODNULL;
  456.         ODWindowState*    windowState = kODNULL;
  457.         
  458.         // Create a list to keep track of the facets we are being
  459.         // displayed in. Also used for maintenance (i.e., Purging memory). 
  460.         _fDisplayFrames = CLinkedList_Create();
  461.     
  462.         // First check to see if the library's global variables have
  463.         // been initialized (meaning another part instantiation is already
  464.         // running).
  465.     
  466.         if ( gGlobalsUsageCount == 0 )
  467.         {
  468.             // Grab a reference to the Session object. This is merely for
  469.             // convenience. 
  470.             session = ODGetSessionFromPart(ev,_fSelf);
  471.             CHECK_ENV(ev);
  472.             
  473.             // Create our globals space. We store the globals in a struct so
  474.             // that we can put them in temp mem. Otherwise, CFM loads the globals
  475.             // with the data fragment of a CFM library in the application heap.
  476.             gGlobals = newGlobals();
  477.         
  478.             // It is required that parts instantiate their menu bars from 
  479.             // the base OpenDoc menu bar. This maintains consistency in the
  480.             // default menu items and their placement.
  481.             // Since the object is a copy, we can add and subtract menus and
  482.             // items without affecting other running parts.
  483.             windowState = ODSession_GetWindowState(session, ev);
  484.             gGlobals->fMenuBar = ODWindowState_CopyBaseMenuBar(windowState, ev);
  485.             CHECK_ENV(ev);
  486.                 
  487.             // We will be using the above foci (shared resources) in this
  488.             // part. For convenience, we tokenize the values here and store
  489.             // them for equivalence tests in the activation methods. 
  490.             gGlobals->fSelectionFocus = ODSession_Tokenize(session, ev, kODSelectionFocus);
  491.             gGlobals->fMenuFocus      = ODSession_Tokenize(session, ev, kODMenuFocus);
  492.             gGlobals->fModalFocus     = ODSession_Tokenize(session, ev, kODModalFocus);
  493.         
  494.             // Also for convenience, we tokenize our part's main presentation
  495.             // and the standard view types.
  496.             gGlobals->fMainPresentation = ODSession_Tokenize(session, ev, kMainPresentation);
  497.         
  498.             gGlobals->fFrameView        = ODSession_Tokenize(session, ev, kODViewAsFrame);
  499.             gGlobals->fLargeIconView = ODSession_Tokenize(session, ev, kODViewAsLargeIcon);
  500.             gGlobals->fSmallIconView = ODSession_Tokenize(session, ev, kODViewAsSmallIcon);
  501.             gGlobals->fThumbnailView = ODSession_Tokenize(session, ev, kODViewAsThumbnail);
  502.             
  503.             // Lastly, we will package the menu and selection focus
  504.             // so that we can request the "set" at activation time.
  505.             arbitrator = ODSession_GetArbitrator(session, ev);
  506.             gGlobals->fUIFocusSet = ODArbitrator_CreateFocusSet(arbitrator, ev);
  507.             CHECK_ENV(ev);
  508.             ODFocusSet_Add(gGlobals->fUIFocusSet, ev, gGlobals->fMenuFocus);
  509.             ODFocusSet_Add(gGlobals->fUIFocusSet, ev, gGlobals->fSelectionFocus);
  510.             CHECK_ENV(ev);
  511.         
  512.             // Determine what Script/Language the part is localized for.
  513.             // This is important/necessary for creating OpenDoc's text objects.
  514.             GetEditorScriptLanguage(ev, &gGlobals->fEditorsScript, &gGlobals->fEditorsLanguage);
  515.             
  516.             // The first client of the global variables is running.
  517.             gGlobalsUsageCount = 1;
  518.         }
  519.         else
  520.         // If the globals have been initialized, we just bump the "usage" count so
  521.         // that we know how many part instances are using them.
  522.         {
  523.             gGlobalsUsageCount++;
  524.         }
  525.         
  526.     SOM_CATCH_ALL
  527.         gGlobalsUsageCount = 0;
  528.     SOM_ENDTRY
  529. }
  530.  
  531. //==============================================================================
  532. #pragma mark    • Storage •
  533. //==============================================================================
  534.  
  535. //------------------------------------------------------------------------------
  536. // Method:        Release
  537. // Origin:        ODPart
  538. //
  539. // Description:    This method is called each time an object releases a reference
  540. //                to the part. If the refcount falls to 0, the part should
  541. //                release the fSelf part reference.
  542. //
  543. // Warning:        If the part releases any other object when the refcount falls to
  544. //                zero, it will need to override the IncrementRefCount method so
  545. //                that the object can be referenced again if the parts refcount
  546. //                should be incremented before it is deleted.
  547. //------------------------------------------------------------------------------
  548.  
  549. SOM_Scope    void
  550. SOMLINK        SamplePart__Release
  551.             (
  552.                 SampleCode_SamplePart*        somSelf,
  553.                 Environment*                ev
  554.             )
  555. {
  556.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  557.     SampleCode_SamplePartMethodDebug("SamplePart","Release");
  558.  
  559.     SOM_TRY
  560.         
  561.         SampleCode_SamplePart_parent_ODPart_Release(somSelf,ev);
  562.         CHECK_ENV(ev);
  563.     
  564.         if ( ODPart_GetRefCount(_fSelf, ev) == 0 )
  565.         {
  566.             ODDraft* draft = ODGetDraftFromPart(ev,_fSelf);
  567.             ODDraft_ReleasePart(draft, ev, _fSelf);
  568.         }
  569.         
  570.     SOM_CATCH_ALL
  571.     SOM_ENDTRY
  572. }
  573.  
  574. //--------------------------------------------------------------------
  575. // Method:        ReleaseAll
  576. // Origin:        ODPersistentObject
  577. //
  578. // Description:    This method is called just prior to the part being
  579. //                deleted by the Draft. The part must release all
  580. //                references to all refcounted objects it has stored
  581. //                internally; not doing so, will cause an "invalid ref
  582. //                count" exception/error.
  583. //------------------------------------------------------------------- 
  584.  
  585. SOM_Scope    void
  586. SOMLINK        SamplePart__ReleaseAll
  587.             (
  588.                 SampleCode_SamplePart*        somSelf,
  589.                 Environment*                ev
  590.             )
  591. {
  592.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  593.     SampleCode_SamplePartMethodDebug("SamplePart","ReleaseAll");
  594.  
  595.     SOM_TRY
  596.         // If the last part instance using the globals is released,
  597.         // we need to clean up and delete the globals.
  598.         
  599.         if ( --gGlobalsUsageCount == 0 )
  600.         {
  601.             // Release the menubar.
  602.             ODReleaseObject(ev, gGlobals->fMenuBar);
  603.             
  604.             // Delete the focusSet
  605.             ODDeleteObject_C(gGlobals->fUIFocusSet);
  606.  
  607.             // Release the thumbnail (PICT) resource.
  608.             if ( gGlobals->fThumbnail )
  609.             {
  610.                 ReleaseResource(gGlobals->fThumbnail);
  611.                 gGlobals->fThumbnail = kODNULL;
  612.             }
  613.             
  614.             // Now, clean up the globals struct.
  615.             deleteGlobals(&gGlobals);
  616.         }
  617.  
  618.         // Remove and release our display frames.
  619.         if ( _fDisplayFrames)
  620.         {
  621.             CLink* link;
  622.             for ( link = CLinkedList_First(_fDisplayFrames);
  623.                  CLink_Content(link);
  624.                  link = CLink_Next(link) )
  625.             {
  626.                 CFrameProxy* proxy = (CFrameProxy*) CLink_Content(link);
  627.                 // Delete the proxy object and its contents. The frame's
  628.                 // refcount will be decremented in the proxy destructor.
  629.                 link = link->prev;
  630.                 CLinkedList_Remove(_fDisplayFrames, proxy);
  631.                 CFrameProxy_Delete(&proxy, ev);
  632.             }
  633.         }
  634.  
  635.         // Delete the display frame collection.
  636.         CLinkedList_Delete(_fDisplayFrames);
  637.         
  638.         SampleCode_SamplePart_parent_ODPart_ReleaseAll(somSelf,ev);
  639.         
  640.     SOM_CATCH_ALL
  641.         // If something goes wrong while we are cleaning up, we must
  642.         // let the Draft know because there may be some refcounted objects
  643.         // which did not get released. Not to mention, possible memory
  644.         // leaks.
  645.     SOM_ENDTRY
  646. }
  647.  
  648. //------------------------------------------------------------------------------
  649. // Method:        Purge
  650. // Origin:        ODObject
  651. //
  652. // Description:    This method is called when the OpenDoc requires more memory for
  653. //                allocating objects and just before a part is deleted. The part
  654. //                should free up as much memory as it can.
  655. //
  656. //                The part determines which views are being "used" in its display
  657. //                frames. The resources for the unused view types are then purged.
  658. //------------------------------------------------------------------------------
  659.  
  660. SOM_Scope    ODSize
  661. SOMLINK        SamplePart__Purge
  662.             (
  663.                 SampleCode_SamplePart*        somSelf,
  664.                 Environment*                ev,
  665.                 ODSize                        size /* unused */
  666.             )
  667. {
  668.     ODSize bytesFreed = 0; 
  669.  
  670.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  671.     SampleCode_SamplePartMethodDebug("SamplePart","Purge");
  672.  
  673.     SOM_TRY
  674.         
  675.         ODBoolean    usingThumbnail  = kODFalse;
  676.         CLink*        link;
  677.         
  678.         // Purge is called during the creation of stationery. However,
  679.         // we have not created our internal display frames list, so 
  680.         // trying to iterate over it would be fatal.
  681.         if ( _fDisplayFrames == kODNULL) return 0;
  682.         
  683.         // Iterate over the frames we are displayed through and determine which
  684.         // view types are currently in use. 
  685.         
  686.         for ( link = CLinkedList_First(_fDisplayFrames);
  687.               CLink_Content(link);
  688.               link = CLink_Next(link) )
  689.         {
  690.             // If the display frame is real (has been "connected" or was "added")
  691.             // get it's view type; otherwise, ignore it.
  692.             CFrameProxy* proxy = (CFrameProxy*) CLink_Content(link);
  693.             if ( CFrameProxy_FrameIsLoaded(proxy, ev) )
  694.             {
  695.                 ODTypeToken    frameView;
  696.                 ODFrame*    frame = CFrameProxy_GetFrame(proxy, ev);
  697.                 CHECK_ENV(ev);
  698.                 
  699.                 frameView = ODFrame_GetViewType(frame, ev);
  700.                 
  701.                 if ( frameView == gGlobals->fThumbnailView )
  702.                     usingThumbnail = kODTrue;
  703.     
  704.                 // Release the frame reference, but don't get rid of the
  705.                 // proxy object because we're not done with the frame. If
  706.                 // all parts release their references the frame will be
  707.                 // purged from memory.
  708.                 CFrameProxy_Purge(proxy, ev);
  709.             }
  710.         }
  711.         
  712.         // Based on the usage of the supported view types, free up as much
  713.         // memory as possible. 
  714.     
  715.         if ( !usingThumbnail && (gGlobals->fThumbnail != kODNULL) )
  716.         {
  717.             bytesFreed += (ODSize) ODGetHandleSize(gGlobals->fThumbnail);
  718.             ReleaseResource(gGlobals->fThumbnail);
  719.             gGlobals->fThumbnail = kODNULL;
  720.         }
  721.         
  722.     SOM_CATCH_ALL
  723.         bytesFreed = 0;
  724.     SOM_ENDTRY
  725.     
  726.     return bytesFreed;
  727. }
  728.  
  729. //------------------------------------------------------------------------------
  730. // Method:        InternalizeStateInfo
  731. // Origin:        SamplePart
  732. //
  733. // Description:    This method is used to read in "state" information for the part.
  734. //                This is information related to the workings of the part editor,
  735. //                not the content.
  736. //
  737. //                The part rights out a list of weak references to its display
  738. //                frames. This allows the part to reuse the same display frames
  739. //                each time the document is opened. Those references are read
  740. //                back in and validated here.
  741. //
  742. // Note:        The function StorageUnitGetValue simplifies the use of
  743. //                ODByteArrary, which is required the StorageUnit interface. Look
  744. //                in StorUtil.h/cpp for an example of using the ODByteArray struct.
  745. //------------------------------------------------------------------------------
  746.  
  747. SOM_Scope    void
  748. SOMLINK        SamplePart__InternalizeStateInfo
  749.             (
  750.                 SampleCode_SamplePart*        somSelf,
  751.                 Environment*                ev,
  752.                 ODStorageUnit*                storageUnit
  753.             )
  754. {
  755.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  756.     SampleCode_SamplePartMethodDebug("SamplePart","InternalizeStateInfo");
  757.  
  758.     SOM_TRY
  759.  
  760.         // Internalize the part's display frame list.
  761.     
  762.         if ( ODStorageUnit_Exists(storageUnit, ev, kODPropDisplayFrames,
  763.                                         kODWeakStorageUnitRefs, 0) )
  764.         {
  765.             ODULong size;
  766.             ODULong offset;
  767.             
  768.             ODStorageUnit_Focus(storageUnit, ev, kODPropDisplayFrames,
  769.                                     kODPosUndefined, kODWeakStorageUnitRefs, 0,
  770.                                     kODPosUndefined);
  771.             CHECK_ENV(ev);
  772.                                         
  773.             size = ODStorageUnit_GetSize(storageUnit, ev);
  774.             CHECK_ENV(ev);
  775.             ODStorageUnit_SetOffset(storageUnit, ev, 0);    
  776.             CHECK_ENV(ev);
  777.         
  778.             for ( offset = 0; offset < size; offset += kODStorageUnitRefSize )
  779.             {
  780.                 TRY
  781.                     ODStorageUnitRef weakRef;
  782.  
  783.                     StorageUnitGetValue_C(storageUnit, ev, kODStorageUnitRefSize, (ODPtr)&weakRef);
  784.                     CHECK_ENV(ev);
  785.     
  786.                     if ( ODStorageUnit_IsValidStorageUnitRef(storageUnit, ev,
  787.                             weakRef) )
  788.                     {    
  789.                         CFrameProxy* proxy;
  790.                         ODID id;
  791.                         
  792.                         // We lazily internalize our display frames, meaning we don't "get"
  793.                         // the frame until we absolutely need it. This reduces the time
  794.                         // to internalize the part and the amount of memory needed.
  795.                         
  796.                         // Convert the reference into a runtime id.
  797.                         id = ODStorageUnit_GetIDFromStorageUnitRef(storageUnit, ev,
  798.                                                                         weakRef);
  799.                         CHECK_ENV(ev);
  800.                         // Acquire a new frame to support the lazy internalization.
  801.                         proxy = CFrameProxy_Create();
  802.                         CFrameProxy_InitFrameProxyWithID(proxy, id, 
  803.                                                 ODGetDraftFromSU(ev,storageUnit));
  804.     
  805.                         // Add the frame to the display frame collection.
  806.                         CLinkedList_Add(_fDisplayFrames, (ODPtr)proxy);
  807.                     }
  808.                     CHECK_ENV(ev);
  809.                 CATCH_ALL
  810.                     // consume exception
  811.                 ENDTRY
  812.             }
  813.         }
  814.         CHECK_ENV(ev);
  815.  
  816.     SOM_CATCH_ALL
  817.     SOM_ENDTRY
  818. }
  819.  
  820. //------------------------------------------------------------------------------
  821. // Method:        InternalizeContent
  822. // Origin:        SamplePart
  823. //
  824. // Description:    This method is called during initialization of the part from an
  825. //                existing document. The content of the part should be read in.
  826. //
  827. //                The part has no intrinsic content, so the part does nothing.
  828. //                The method is here for completeness.
  829. //------------------------------------------------------------------------------
  830.  
  831. SOM_Scope    void
  832. SOMLINK        SamplePart__InternalizeContent
  833.             (
  834.                 SampleCode_SamplePart*        somSelf,
  835.                 Environment*                ev,
  836.                 ODStorageUnit*                storageUnit
  837.             )
  838. {
  839.     SampleCode_SamplePartMethodDebug("SamplePart","InternalizeContent");
  840. }
  841.  
  842. //------------------------------------------------------------------------------
  843. // Method:        CloneInto
  844. // Origin:        ODPersistentObject
  845. //
  846. // Description:    This method is called during cloning, typically during data
  847. //                interchange operations (ie. Cut/Paste). The part should
  848. //                write out its current state and content.
  849. //------------------------------------------------------------------------------
  850.  
  851. SOM_Scope    void
  852. SOMLINK        SamplePart__CloneInto
  853.              (
  854.                 SampleCode_SamplePart*        somSelf,
  855.                 Environment*                ev,
  856.                 ODDraftKey                    key,
  857.                 ODStorageUnit*                destinationSU,
  858.                 ODFrame*                    initiatingFrame
  859.             )
  860. {
  861.     SampleCode_SamplePartMethodDebug("SamplePart","CloneInto");
  862.     
  863.     SOM_TRY
  864.         
  865.         // This calls back up to the persistent object parent
  866.         // class which copies over our timedate stamp and last modified
  867.         // information. 
  868.         SampleCode_SamplePart_parent_ODPart_CloneInto
  869.                 (somSelf,ev,key,destinationSU,initiatingFrame);
  870.         CHECK_ENV(ev);
  871.     
  872.         // We must first verify that we've never written to this storage unit.
  873.         // If we have, we should do nothing, otherwise we need to write out
  874.         // the current state of the part content. 
  875.         
  876.         if ( ODStorageUnit_Exists(destinationSU, ev, kODPropContents,
  877.                 kSamplePartKind, 0) == kODFalse )
  878.         {
  879.             // Add the properties we need to successfully externalize
  880.             // ourselves into the destination storage unit. 
  881.             _CheckAndAddProperties(somSelf, ev, destinationSU);
  882.             CHECK_ENV(ev);
  883.                     
  884.             // Write out the part's state information. 
  885.             _ExternalizeStateInfo(somSelf, ev, destinationSU, key, initiatingFrame);
  886.             CHECK_ENV(ev);
  887.                 
  888.             // Write out the part's content. 
  889.             _ExternalizeContent(somSelf, ev, destinationSU, key, initiatingFrame);
  890.             CHECK_ENV(ev);
  891.         }
  892.     
  893.     SOM_CATCH_ALL
  894.     SOM_ENDTRY
  895. }
  896.  
  897. //------------------------------------------------------------------------------
  898. // Method:        Externalize
  899. // Origin:        ODPersistentObject
  900. //
  901. // Description:    This method is called when the user saves the document. The part
  902. //                should write out its state and content if changes have occurred
  903. //                and if our storage is writeable.
  904. //
  905. // Note:        The part must call its parent class behavior because one or more
  906. //                of our parent classes contains implementation. This is done in
  907. //                the SOM class.
  908. //------------------------------------------------------------------------------
  909.  
  910. SOM_Scope    void
  911. SOMLINK        SamplePart__Externalize
  912.             (
  913.                 SampleCode_SamplePart*        somSelf,
  914.                 Environment*                ev
  915.             )
  916. {
  917.     ODStorageUnit* storageUnit;
  918.     
  919.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  920.     SampleCode_SamplePartMethodDebug("SamplePart","Externalize");
  921.     
  922.     SOM_TRY
  923.         // First ask our parent classes to externalize.
  924.         SampleCode_SamplePart_parent_ODPart_Externalize(somSelf,ev);
  925.         CHECK_ENV(ev);
  926.  
  927.         if ( _fDirty && !_fReadOnlyStorage)
  928.         {
  929.             // Get our storage unit. 
  930.             storageUnit = ODPart_GetStorageUnit(somSelf, ev);
  931.             CHECK_ENV(ev);
  932.     
  933.             // Verify that the storage unit has the appropriate properties
  934.             // and values to allow us to run. If not, add them.
  935.             _CheckAndAddProperties(somSelf, ev, storageUnit);
  936.             CHECK_ENV(ev);
  937.         
  938.             // Verify that there are no "bogus" values in the Content
  939.             // property.
  940.             _CleanseContentProperty(somSelf, ev, storageUnit);
  941.             CHECK_ENV(ev);
  942.         
  943.             // Write out the part's state information. 
  944.             _ExternalizeStateInfo(somSelf, ev, storageUnit, kODNULLKey, kODNULL);
  945.             CHECK_ENV(ev);
  946.                 
  947.             // Write out the part's content. 
  948.             _ExternalizeContent(somSelf, ev, storageUnit, kODNULLKey, kODNULL);
  949.             CHECK_ENV(ev);
  950.     
  951.             // Flag our part as no longer being dirty. 
  952.             _fDirty = kODFalse;
  953.         }
  954.         
  955.     SOM_CATCH_ALL
  956.         // Alert the user of the problem.
  957.         _DoDialogBox(somSelf, ev, kODNULL, kErrorBoxID, kErrExternalizeFailed);
  958.         // Change the exception value, so the DocShell doesn't display an
  959.         // error dialog.
  960.         ODSetSOMException(ev, kODErrAlreadyNotified, kODNULL);
  961.     SOM_ENDTRY
  962. }
  963.  
  964. //------------------------------------------------------------------------------
  965. // Method:        ExternalizeKinds
  966. // Origin:        ODPart
  967. //
  968. // Description:    This method is called when the user wants to save the document
  969. //                with multiple representations of the data. This is especially
  970. //                useful for increasing the portability of documents
  971. //                cross-platform.
  972. //
  973. //                A part should verify each kind is valid, that it exists in
  974. //                the content property in the correct order, and write the data.
  975. //------------------------------------------------------------------------------
  976.  
  977. SOM_Scope    void
  978. SOMLINK        SamplePart__ExternalizeKinds(SampleCode_SamplePart *somSelf,
  979.         Environment *ev,
  980.         ODTypeList* kindset)
  981. {
  982.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  983.     SampleCode_SamplePartMethodDebug("SamplePart","ExternalizeKinds");
  984.  
  985.     SOM_TRY
  986.     
  987.         if ( !_fReadOnlyStorage )
  988.         {
  989.             ODType                kind;
  990.             ODBoolean            preferredKindWritten = kODFalse;
  991.             ODTypeListIterator* tliter = kODNULL;
  992.             ODStorageUnit*        storageUnit;
  993.             
  994.             ODVolatile(tliter);
  995.         
  996.             // Get our storage unit. 
  997.             storageUnit = ODPart_GetStorageUnit(somSelf, ev);
  998.             CHECK_ENV(ev);
  999.     
  1000.             // Verify that the storage unit has the appropriate properties
  1001.             // and values to allow us to run. If not, add them.
  1002.             _CheckAndAddProperties(somSelf, ev, storageUnit);
  1003.             CHECK_ENV(ev);
  1004.         
  1005.             // Verify that there are no "bogus" values in the Content
  1006.             // property.
  1007.             _CleanseContentProperty(somSelf, ev, storageUnit);
  1008.             CHECK_ENV(ev);
  1009.     
  1010.             // Iterate over the kindset and write out the content types
  1011.             // that we support.
  1012.             tliter = ODTypeList_CreateTypeListIterator(kindset, ev);
  1013.             CHECK_ENV(ev);
  1014.     
  1015.             TRY
  1016.                 for ( kind = ODTypeListIterator_First(tliter, ev);
  1017.                         ODTypeListIterator_IsNotComplete(tliter, ev);
  1018.                         kind = ODTypeListIterator_Next(tliter, ev) )
  1019.                 {
  1020.         
  1021.                     // Check to see if this is a kind we support. If so, write it.
  1022.                     if ( ODISOStrCompare(kind, kSamplePartKind) == 0 )
  1023.                     {
  1024.                         // Write out the part's content.
  1025.                         _ExternalizeContent(somSelf, ev, storageUnit, 
  1026.                                                                 kODNULLKey, kODNULL);
  1027.                         // This is our preferrend kind so we don't need to write it again.
  1028.                         // Part editors with more than one kind need to test each kind
  1029.                         // against the preferred kind to make sure it's been written.
  1030.                         preferredKindWritten = kODTrue;
  1031.                     }
  1032.                 }
  1033.                 CHECK_ENV(ev);
  1034.                 // Delete the iterator;
  1035.                 ODDeleteObject_C(tliter);
  1036.             CATCH_ALL
  1037.                 // Delete the iterator;
  1038.                 ODDeleteObject_C(tliter);
  1039.                 RERAISE;
  1040.             ENDTRY
  1041.             
  1042.             // Write out the part's state information.
  1043.             _ExternalizeStateInfo(somSelf, ev, storageUnit, kODNULLKey, kODNULL);
  1044.             CHECK_ENV(ev);
  1045.     
  1046.             // Even if the kind set contains no types we support, we must at least
  1047.             // write out our current "preferred" kind.
  1048.             if ( preferredKindWritten == kODFalse )
  1049.             {
  1050.                 // Write out the part's preferred content kind, which, for SamplePart,
  1051.                 // is the only kind.
  1052.                 _ExternalizeContent(somSelf, ev, storageUnit, kODNULLKey, kODNULL);
  1053.                 CHECK_ENV(ev);
  1054.             }
  1055.         }
  1056.     
  1057.     SOM_CATCH_ALL
  1058.     SOM_ENDTRY
  1059. }
  1060.  
  1061. //------------------------------------------------------------------------------
  1062. // Method:        ChangeKind
  1063. // Origin:        ODPart
  1064. //
  1065. // Description:    This method is called when the changes the part's primary kind
  1066. //                and/or when the part editor is switched via the Info dialog.
  1067. //
  1068. //                The editor should record the new "preferred" kind and change the
  1069. //                UI, if necessary, to allow editing of that kind. Don't write the
  1070. //                properties/values/data until the Externalize is called.
  1071. //------------------------------------------------------------------------------
  1072.  
  1073. SOM_Scope void  SOMLINK SamplePart__ChangeKind(SampleCode_SamplePart *somSelf,
  1074.         Environment *ev,
  1075.         ODType kind)
  1076. {
  1077.     SampleCode_SamplePartMethodDebug("SamplePart","ChangeKind");
  1078.  
  1079.     SOM_TRY
  1080.         // SamplePart only has one kind, but we need to make sure the "Preferred Kind"
  1081.         // property has the correct value.
  1082.         if ( ODISOStrCompare(kind, kSamplePartKind) == 0 )
  1083.         {
  1084.             // Get our storage unit.
  1085.             ODStorageUnit* storageUnit = ODPart_GetStorageUnit(somSelf, ev);
  1086.             
  1087.             TRY
  1088.                 ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, kODISOStr, kSamplePartKind);
  1089.                 
  1090.                 // Changing our kind dirties our content.
  1091.                 _SetDirty(somSelf, ev);
  1092.                 
  1093.                 // Immediately externalize ourselves in the "new" format.
  1094.                 SamplePart__Externalize(somSelf, ev);
  1095.                 CHECK_ENV(ev);
  1096.                 
  1097.             CATCH_ALL
  1098.                 // Remove the property and value if something went wrong.
  1099.                 ODStorageUnit_Remove(storageUnit, ev);
  1100.             ENDTRY
  1101.         }
  1102.         else
  1103.             THROW(kODErrInvalidValueType);
  1104.     
  1105.     SOM_CATCH_ALL
  1106.     SOM_ENDTRY
  1107.  
  1108. }
  1109.  
  1110.  
  1111. //------------------------------------------------------------------------------
  1112. // Method:        ExternalizeStateInfo
  1113. // Origin:        SamplePart
  1114. //
  1115. // Description:    This method is called during externalization of the part. The
  1116. //                current "state" of the part should be written out. This "state"
  1117. //                information may be lost during Data Interchange operations, so
  1118. //                the part needs to recover gracefully if information is missing
  1119. //                or incomplete.
  1120. //
  1121. // Note:        The function StorageUnitSetValue is a macro which simplifies
  1122. //                the use of ODByteArrary, which is required by the StorageUnit
  1123. //                interface. Look in StorUtil.h/cpp for an example of using the
  1124. //                ODByteArray struct.
  1125. //------------------------------------------------------------------------------
  1126.  
  1127. SOM_Scope    void
  1128. SOMLINK        SamplePart__ExternalizeStateInfo
  1129.             (
  1130.                 SampleCode_SamplePart*        somSelf,
  1131.                 Environment*                ev,
  1132.                 ODStorageUnit*                storageUnit,
  1133.                 ODDraftKey                    key,
  1134.                 ODFrame*                    scopeFrame
  1135.             )
  1136. {
  1137.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1138.     SampleCode_SamplePartMethodDebug("SamplePart","ExternalizeStateInfo");
  1139.  
  1140.     SOM_TRY
  1141.         ODID                scopeFrameID;
  1142.         ODDraft*            fromDraft;
  1143.         CLink*                link;
  1144.         
  1145.         scopeFrameID = ( scopeFrame ? ODFrame_GetID(scopeFrame,ev) : kODNULLID );
  1146.         CHECK_ENV(ev);
  1147.         
  1148.         fromDraft = ODGetDraftFromPart(ev,_fSelf);
  1149.         CHECK_ENV(ev);
  1150.         
  1151.         // Externalize the part's display frame list.
  1152.     
  1153.         ODStorageUnit_Focus(storageUnit, ev, kODPropDisplayFrames, kODPosUndefined,
  1154.                                     kODWeakStorageUnitRefs, 0, kODPosUndefined);
  1155.         CHECK_ENV(ev);
  1156.         
  1157.         // Persistent object references are stored in a side table, rather than
  1158.         // in the property/value stream. Thus, deleting the contents of a value
  1159.         // will not "delete" the references previously written to that value. To
  1160.         // completely "delete" all references written to the value, we must
  1161.         // remove the value and add it back.
  1162.         ODStorageUnit_Remove(storageUnit, ev);
  1163.         CHECK_ENV(ev);
  1164.         
  1165.         ODStorageUnit_AddValue(storageUnit, ev, kODWeakStorageUnitRefs);
  1166.         CHECK_ENV(ev);
  1167.     
  1168.         for ( link = CLinkedList_First(_fDisplayFrames);
  1169.              CLink_Content(link);
  1170.              link = CLink_Next(link) )
  1171.         {
  1172.             ODID                frameID;
  1173.             CFrameProxy*        proxy;
  1174.             ODStorageUnitRef    weakRef;
  1175.  
  1176.             // Get the ID of the frame we are going to weakly reference.
  1177.             proxy = (CFrameProxy*) CLink_Content(link);
  1178.             frameID = CFrameProxy_GetID(proxy);
  1179.             
  1180.             // If a draft key exists, then we are being cloned to another draft.
  1181.             // We must "weak" clone our display frame and reference the cloned
  1182.             // frame. The part re-uses the frameID variable so there aren't two
  1183.             // different GetWeakStorageUnitRef calls.
  1184.             if ( key )
  1185.             {
  1186.                 frameID = ODDraft_WeakClone(fromDraft, ev, key, frameID, kODNULLID, scopeFrameID);
  1187.                 CHECK_ENV(ev);
  1188.             }
  1189.             
  1190.             // Write out weak references to each of the part's display frames.
  1191.             ODStorageUnit_GetWeakStorageUnitRef(storageUnit, ev, frameID, weakRef);
  1192.             CHECK_ENV(ev);
  1193.             
  1194.             StorageUnitSetValue_C(storageUnit, ev, kODStorageUnitRefSize, (ODPtr)&weakRef);
  1195.         }
  1196.     
  1197.     SOM_CATCH_ALL
  1198.     SOM_ENDTRY
  1199. }
  1200.  
  1201. //------------------------------------------------------------------------------
  1202. // Method:        ExternalizeContent
  1203. // Origin:        SamplePart
  1204. //
  1205. // Description:    This method is called during exteralization of the part. The
  1206. //                content of the part should be written out.
  1207. //
  1208. //                The part has no intrinsic content, so the part does nothing.
  1209. //                The method is here for completeness.
  1210. //------------------------------------------------------------------------------
  1211.  
  1212. SOM_Scope    void
  1213. SOMLINK        SamplePart__ExternalizeContent
  1214.             (
  1215.                 SampleCode_SamplePart*        somSelf,
  1216.                 Environment*                ev,
  1217.                 ODStorageUnit*                storageUnit, /* unused */
  1218.                 ODDraftKey                    key,         /* unused */
  1219.                 ODFrame*                    scopeFrame /* unused */
  1220.             )
  1221. {
  1222.     SampleCode_SamplePartMethodDebug("SamplePart","ExternalizeContent");
  1223.  
  1224.     // You would write out your part's content after focusing to your
  1225.     // content property. 
  1226.     
  1227. }
  1228.  
  1229. //------------------------------------------------------------------------------
  1230. // Method:        CleanseContentProperty
  1231. // Oringin:        SamplePart
  1232. //
  1233. // Description:    This method is called during exteralization of the part so that
  1234. //                the part can remove any value in the content property
  1235. //                that it cannot "accurately" write to.
  1236. //
  1237. // Note:        "Additional" values will be added to a part's content property
  1238. //                during Drag & Drop operations.
  1239. //------------------------------------------------------------------------------
  1240.  
  1241. SOM_Scope    void
  1242. SOMLINK        SamplePart__CleanseContentProperty
  1243.             (
  1244.                 SampleCode_SamplePart*        somSelf,
  1245.                 Environment*                ev,
  1246.                 ODStorageUnit*                storageUnit
  1247.             )
  1248. {
  1249.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1250.     SampleCode_SamplePartMethodDebug("SamplePart","CleanseContentProperty");
  1251.  
  1252.     SOM_TRY
  1253.         
  1254.         ODULong        numValues;
  1255.         ODULong        index;
  1256.         ODValueType    value;
  1257.         
  1258.         ODVolatile(value);
  1259.     
  1260.         ODStorageUnit_Focus(storageUnit, ev, kODPropContents, kODPosUndefined, 
  1261.                                 kODNULL, 0, kODPosAll);
  1262.         
  1263.         numValues = ODStorageUnit_CountValues(storageUnit, ev);
  1264.         
  1265.         for (index = numValues; index >= 1; index--)
  1266.         {
  1267.             // Index from n to 1 through the values.
  1268.             ODStorageUnit_Focus(storageUnit, ev, kODPropContents, kODPosUndefined, 
  1269.                                     kODNULL, index, kODPosUndefined);
  1270.                                     
  1271.             TRY
  1272.                 // Get the ISO type name for the value. The temp object
  1273.                 // will automatically delete the returned value when this
  1274.                 // scope is exited.
  1275.                 value = ODStorageUnit_GetType(storageUnit, ev);
  1276.                 
  1277.                 // If the value type is not one we support, remove it.
  1278.                 if ( ODISOStrCompare(value, kSamplePartKind) != 0 )
  1279.                     ODStorageUnit_Remove(storageUnit, ev);
  1280.         
  1281.                 ODDisposePtr(value);
  1282.                 
  1283.             CATCH_ALL
  1284.                 ODDisposePtr(value);
  1285.                 RERAISE;
  1286.             ENDTRY
  1287.         }
  1288.     
  1289.     SOM_CATCH_ALL
  1290.     SOM_ENDTRY
  1291. }
  1292.  
  1293. //------------------------------------------------------------------------------
  1294. // Method:        CheckAndAddProperties
  1295. // Origin:        SamplePart
  1296. //
  1297. // Description:    This method is called during externalization of the part to
  1298. //                verify that all the properties needed to persistently represent
  1299. //                the current running state of the part.
  1300. //
  1301. //                The part adds the default content property, a preferred editor
  1302. //                property (to aid in part binding), a display frames property.
  1303. //
  1304. // Note:        The function StorageUnitSetValue is a macro which simplifies
  1305. //                the use of ODByteArrary, which is required the StorageUnit
  1306. //                interface. Look in StorUtil.h/cpp for an example of using the
  1307. //                ODByteArray struct.
  1308. //------------------------------------------------------------------------------
  1309.  
  1310. SOM_Scope    void
  1311. SOMLINK        SamplePart__CheckAndAddProperties
  1312.             (
  1313.                 SampleCode_SamplePart*        somSelf,
  1314.                 Environment*                ev,
  1315.                 ODStorageUnit*                storageUnit
  1316.             )
  1317. {
  1318.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1319.     SampleCode_SamplePartMethodDebug("SamplePart","CheckAndAddProperties");
  1320.  
  1321.     SOM_TRY
  1322.     
  1323.         // Create our content property and preferred content property kind.
  1324.     
  1325.         if ( !ODStorageUnit_Exists(storageUnit, ev, kODPropContents, kODNULL, 0) )
  1326.             ODStorageUnit_AddProperty(storageUnit, ev, kODPropContents);
  1327.         if ( !ODStorageUnit_Exists(storageUnit, ev, kODPropContents, kSamplePartKind, 0) )
  1328.         {
  1329.             ODStorageUnit_Focus(storageUnit, ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosAll);
  1330.             ODStorageUnit_AddValue(storageUnit, ev, kSamplePartKind);
  1331.         }
  1332.         
  1333.         // Since we are setting up the preferred kind property, we just write
  1334.         // out our default "kind" for the editor. We can write out the user
  1335.         // chosen kind in the ExternalizeStateInfo method.
  1336.     
  1337.         if ( !ODStorageUnit_Exists(storageUnit, ev, kODPropPreferredKind, kODNULL, 0) )
  1338.         {
  1339.             TRY
  1340.                 ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, kODISOStr, kSamplePartKind);
  1341.             CATCH_ALL
  1342.                 // Remove the property and value if something went wrong.
  1343.                 ODStorageUnit_Remove(storageUnit, ev);
  1344.             ENDTRY
  1345.         }
  1346.     
  1347.         // Add our display frame list.
  1348.         
  1349.         if ( !ODStorageUnit_Exists(storageUnit, ev, kODPropDisplayFrames, kODNULL, 0) )
  1350.             ODStorageUnit_AddProperty(storageUnit, ev, kODPropDisplayFrames);
  1351.         if ( !ODStorageUnit_Exists(storageUnit, ev, kODPropDisplayFrames,
  1352.                     kODWeakStorageUnitRefs, 0) )
  1353.         {
  1354.             ODStorageUnit_Focus(storageUnit, ev, kODPropDisplayFrames, kODPosUndefined, kODNULL, 0, kODPosAll);
  1355.             ODStorageUnit_AddValue(storageUnit, ev, kODWeakStorageUnitRefs);
  1356.         }
  1357.         
  1358.     SOM_CATCH_ALL
  1359.     SOM_ENDTRY
  1360. }
  1361.  
  1362. //------------------------------------------------------------------------------
  1363. // Method:        SetDirty
  1364. // Origin:        SamplePart
  1365. //
  1366. // Description:    This method is called by the part when the content or state of
  1367. //                the part has been modified by the user and the "Save" menu item
  1368. //                should be enabled.
  1369. //------------------------------------------------------------------------------
  1370.  
  1371. SOM_Scope    void
  1372. SOMLINK        SamplePart__SetDirty
  1373.              (
  1374.                 SampleCode_SamplePart*        somSelf,
  1375.                 Environment*                ev
  1376.             )
  1377. {
  1378.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1379.     SampleCode_SamplePartMethodDebug("SamplePart","SetDirty");
  1380.  
  1381.     SOM_TRY
  1382.     
  1383.         // There is no need to repeatedly tell the draft we have
  1384.         // changed; once is sufficient.
  1385.         if ( !_fDirty & !_fReadOnlyStorage)
  1386.         {
  1387.             ODDraft* draft = ODGetDraftFromPart(ev,_fSelf);
  1388.             ODDraft_SetChangedFromPrev(draft, ev);
  1389.     
  1390.             _fDirty = kODTrue;
  1391.         }
  1392.     
  1393.     SOM_CATCH_ALL
  1394.     SOM_ENDTRY
  1395. }
  1396.  
  1397. //------------------------------------------------------------------------------
  1398. // Method:        ReadPartInfo
  1399. //
  1400. // Description:    When a frame is being internalized by the Draft, it will ask the
  1401. //                owner (part) to read in its info annotation on the frame.
  1402. //
  1403. //                The part uses a helper struct to encapsulate the information
  1404. //                we store with each frame, so we let it internalize itself from
  1405. //                the storage unit view.
  1406. //------------------------------------------------------------------------------
  1407.  
  1408. SOM_Scope    ODInfoType
  1409. SOMLINK        SamplePart__ReadPartInfo
  1410.             (
  1411.                 SampleCode_SamplePart*    somSelf,
  1412.                 Environment*            ev,
  1413.                 ODFrame*                frame,
  1414.                 ODStorageUnitView*        storageUnitView
  1415.             )
  1416. {
  1417.     CFrameInfo* frameInfo = kODNULL;
  1418.     
  1419.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1420.     SampleCode_SamplePartMethodDebug("SamplePart","ReadPartInfo");
  1421.  
  1422.     ODVolatile(frameInfo);
  1423.  
  1424.     SOM_TRY
  1425.         frameInfo = CFrameInfo_Create(ODGetSessionFromPart(ev,_fSelf));
  1426.         CFrameInfo_InitFromStorage(frameInfo, ev, storageUnitView);
  1427.         CHECK_ENV(ev);
  1428.     SOM_CATCH_ALL
  1429.         CFrameInfo_Delete( &frameInfo, ev );
  1430.     SOM_ENDTRY
  1431.     
  1432.     return (ODInfoType)frameInfo;
  1433. }
  1434.  
  1435. //------------------------------------------------------------------------------
  1436. // Method:        WritePartInfo
  1437. //
  1438. // Description:    When a frame is being externalized by the Draft, it
  1439. //                will ask the owner (part) to write out its info
  1440. //                annotation on the frame.
  1441. //
  1442. // Description:    When a frame is being externalized by the Draft, it will ask the
  1443. //                owner (part) to write out its info annotation on the frame.
  1444. //
  1445. //                The part uses a struct to encapsulate the information
  1446. //                we store with each frame, and we use a utility function to
  1447. //                externalize it to the storage unit view.
  1448. //------------------------------------------------------------------------------
  1449.  
  1450. SOM_Scope    void
  1451. SOMLINK        SamplePart__WritePartInfo
  1452.             (
  1453.                 SampleCode_SamplePart*        somSelf,
  1454.                 Environment*                ev,
  1455.                 ODInfoType                    partInfo,
  1456.                 ODStorageUnitView*            storageUnitView
  1457.             )
  1458. {
  1459.     SampleCode_SamplePartMethodDebug("SamplePart","WritePartInfo");
  1460.  
  1461.     SOM_TRY
  1462.         // Tell our frame info class to write itself out into the pre-
  1463.         // focused storage unit. 
  1464.         CFrameInfo_Externalize((CFrameInfo*) partInfo, ev, storageUnitView);
  1465.         CHECK_ENV(ev);
  1466.         
  1467.     SOM_CATCH_ALL
  1468.     SOM_ENDTRY
  1469. }
  1470.  
  1471. //------------------------------------------------------------------------------
  1472. // Method:        ClonePartInfo
  1473. //
  1474. // Description:    When a frame is being cloned by the Draft, it will ask the owner
  1475. //                (part) to clone its info annotation on the frame.
  1476. //
  1477. //                The part uses a struct to encapsulate the information
  1478. //                we store with each frame, and we use a utility function to clone
  1479. //                the info to the storage unit view.
  1480. //------------------------------------------------------------------------------
  1481.  
  1482. SOM_Scope    void
  1483. SOMLINK        SamplePart__ClonePartInfo
  1484.             (
  1485.                 SampleCode_SamplePart*        somSelf,
  1486.                 Environment*                ev,
  1487.                 ODDraftKey                    key,
  1488.                   ODInfoType                    partInfo,
  1489.                 ODStorageUnitView*            storageUnitView,
  1490.                 ODFrame*                    scopeFrame
  1491.             )
  1492. {
  1493.     SOM_Trace("SamplePart","ClonePartInfo");
  1494.  
  1495.     SOM_TRY
  1496.         // Tell our frame info class to write itself out into the pre-
  1497.         // focused storage unit.
  1498.         CFrameInfo_CloneInto((CFrameInfo*) partInfo, ev, key, storageUnitView, scopeFrame);
  1499.         CHECK_ENV(ev);
  1500.  
  1501.     SOM_CATCH_ALL
  1502.     SOM_ENDTRY
  1503. }
  1504.  
  1505. //==============================================================================
  1506. #pragma mark    • Layout •
  1507. //==============================================================================
  1508.  
  1509. //------------------------------------------------------------------------------
  1510. // Method:        DisplayFrameAdded
  1511. // Origin:        ODPart
  1512. //
  1513. // Description:    This method is called in response to a frame being created for
  1514. //                the part.
  1515. //
  1516. //                The part records the existence of a new display frame in its
  1517. //                internal display frame list, as well as, verify that the frame
  1518. //                is "set up" correctly (i.e., valid viewType). The part also
  1519. //                creates and stores its "frame info" class in the new frame. 
  1520. //------------------------------------------------------------------------------
  1521.  
  1522. SOM_Scope    void
  1523. SOMLINK        SamplePart__DisplayFrameAdded
  1524.             (
  1525.                 SampleCode_SamplePart*        somSelf,
  1526.                 Environment*                ev,
  1527.                 ODFrame*                    frame
  1528.             )
  1529. {
  1530.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1531.     SampleCode_SamplePartMethodDebug("SamplePart","DisplayFrameAdded");
  1532.  
  1533.     // If we are being embedded into another part, the presentation field
  1534.     // will (most likely) be unset; we need to set it something meaningful.
  1535.     // The view field may also be null, if so, we prefer to be displayed
  1536.     // in a frame view. 
  1537.  
  1538.     SOM_TRY
  1539.  
  1540.         CFrameInfo*     frameInfo;
  1541.         CFrameProxy*    proxy;
  1542.     
  1543.         if ( ODFrame_GetPresentation(frame, ev) != gGlobals->fMainPresentation  )
  1544.         {
  1545.             ODFrame_SetPresentation(frame, ev, gGlobals->fMainPresentation);
  1546.             CHECK_ENV(ev);
  1547.         }
  1548.         CHECK_ENV(ev);
  1549.         
  1550.         if ( ODFrame_GetViewType(frame, ev) == kODNullTypeToken )
  1551.         {
  1552.             ODFrame_SetViewType(frame, ev, gGlobals->fFrameView);
  1553.             CHECK_ENV(ev);
  1554.         }
  1555.         CHECK_ENV(ev);
  1556.             
  1557.         // Hang our "state" info off of the new display frame. We use
  1558.         // the CFrameInfo object for activation, updating, and window
  1559.         // maintenance.
  1560.         frameInfo = CFrameInfo_Create(ODGetSessionFromPart(ev,_fSelf));
  1561.         ODFrame_SetPartInfo(frame, ev, (ODInfoType)frameInfo);
  1562.         CHECK_ENV(ev);
  1563.             
  1564.         // If the frame being added is a root frame, we know that a window
  1565.         // is associated with this frame. Notify ourselves that we need to 
  1566.         // clean it up when the frame goes away.
  1567.         if ( ODFrame_IsRoot(frame, ev) )
  1568.             CFrameInfo_SetShouldDisposeWindow(frameInfo, kODTrue);
  1569.         CHECK_ENV(ev);
  1570.  
  1571.         // The proxy class will refcount the frame passed to it, so we
  1572.         // don't need to worry about refcounting the display frame.
  1573.         proxy = CFrameProxy_Create();
  1574.         CFrameProxy_InitFrameProxyWithFrame(proxy, ev, frame);
  1575.         CHECK_ENV(ev);
  1576.  
  1577.         // Add the frame to the display frame collection.
  1578.         CLinkedList_Add(_fDisplayFrames, (ODPtr)proxy);
  1579.  
  1580.         // Since we maintain a persistent list of weak references to our
  1581.         // display frames, having one added to the part dirties it.
  1582.         _SetDirty(somSelf, ev);
  1583.         CHECK_ENV(ev);
  1584.  
  1585.     SOM_CATCH_ALL
  1586.     SOM_ENDTRY
  1587. }
  1588.  
  1589. //------------------------------------------------------------------------------
  1590. // Method:        DisplayFrameConnected
  1591. // Origin:        ODPart
  1592. //
  1593. // Description:    This method is called when one of our display frames, previously
  1594. //                written out, is internalized. This method is called instead of
  1595. //                DisplayFrameAdded because a "new" frame is not being created;
  1596. //                an existing one is being reconstituted.
  1597. //
  1598. //                The part first checks to see if we can match its frame to an
  1599. //                ID in the Display frame list; if so, we put the frame into the
  1600. //                proxy. For frames we do not recognize, just add them.
  1601. //------------------------------------------------------------------------------
  1602.  
  1603. SOM_Scope    void
  1604. SOMLINK        SamplePart__DisplayFrameConnected
  1605.             (
  1606.                 SampleCode_SamplePart*        somSelf,
  1607.                 Environment*                ev,
  1608.                 ODFrame*                    frame
  1609.             )
  1610. {
  1611.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1612.     SampleCode_SamplePartMethodDebug("SamplePart","DisplayFrameConnected");
  1613.  
  1614.     SOM_TRY
  1615.     
  1616.         CFrameProxy*    proxy = kODNULL;
  1617.         CLink*            link = kODNULL;
  1618.         ODBoolean        found = kODFalse;
  1619.     
  1620.         // Iterate over our display collection to match the frame with
  1621.         // an existing proxy with the correct frame ID. If we find it,
  1622.         // replace the ID with the actual frame. If we don't find it,
  1623.         // signal an error.
  1624.         for ( link = CLinkedList_First(_fDisplayFrames);
  1625.              CLink_Content(link);
  1626.              link = CLink_Next(link) )
  1627.         {
  1628.             // Get the ID of the frame we are going to weakly reference.
  1629.             proxy = (CFrameProxy*) CLink_Content(link);
  1630.             
  1631.             if ( CFrameProxy_GetID(proxy) == ODFrame_GetID(frame, ev) )
  1632.             {
  1633.                 // The proxy class will refcount the frame passed to it, so we
  1634.                 // don't need to worry about refcounting the display frame.
  1635.                 CFrameProxy_SetFrame(proxy, ev,frame);
  1636.                 CHECK_ENV(ev);
  1637.                 
  1638.                 found = kODTrue;
  1639.             }
  1640.             CHECK_ENV(ev);
  1641.         }
  1642.     
  1643.         // Parts typically operate under the assumption that they have previous
  1644.         // knowledge of a frame before it is connected to it. This knowledge
  1645.         // should come from having read in the frame reference when the part
  1646.         // was internalized. If the frame is an "unknown", the part was probably
  1647.         // bound to another editors storage unit because the editor is missing or
  1648.         // the user changed the editor in the Info dialog. 
  1649.         if ( found )
  1650.         {
  1651.             // If a display frame is connected to us with an unrecognizable
  1652.             // presentation, we need to set it to something meaningful.
  1653.         
  1654.             if ( ODFrame_GetPresentation(frame, ev) != gGlobals->fMainPresentation )
  1655.             {
  1656.                 ODFrame_SetPresentation(frame, ev, gGlobals->fMainPresentation);
  1657.                 CHECK_ENV(ev);
  1658.             }
  1659.             CHECK_ENV(ev);
  1660.             
  1661.             if ( ODFrame_IsRoot(frame, ev) )
  1662.             {
  1663.                 // If the frame being added is a root frame, we know that a window
  1664.                 // is associated with this frame. Notify ourselves that we need to 
  1665.                 // clean it up when the frame goes away.
  1666.                 CFrameInfo* frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  1667.                 CHECK_ENV(ev);
  1668.                 
  1669.                 CFrameInfo_SetShouldDisposeWindow(frameInfo, kODTrue);
  1670.                 
  1671.                 // In addition, we need to verify that the frame is in "frame" view.
  1672.                 // If the user dragged an icon from a document to Finder and then
  1673.                 // opens the resultant document, the view would be "icon". However
  1674.                 // displaying a icon is useless, so we need to change the view to
  1675.                 // frame.
  1676.                 if (  ODFrame_GetViewType(frame, ev) != gGlobals->fFrameView )
  1677.                     ODFrame_SetViewType(frame, ev, gGlobals->fFrameView);    
  1678.                 CHECK_ENV(ev);
  1679.             }
  1680.         }
  1681.         else
  1682.         {
  1683.             // If an unrecognizable frame is connected to us, treat it like a "new"
  1684.             // frame and call our method to add it.
  1685.             _DisplayFrameAdded(somSelf, ev, frame);
  1686.         }
  1687.     
  1688.     SOM_CATCH_ALL
  1689.     SOM_ENDTRY
  1690. }
  1691.  
  1692. //------------------------------------------------------------------------------
  1693. // Method:        DisplayFrameRemoved
  1694. // Origin:        ODPart
  1695. //
  1696. // Description:    This method is called in response to a frame being removed from
  1697. //                the part.
  1698. //
  1699. //                The part removes the frame from its internal display frame list
  1700. //                and reliquishes any foci that it still owned. Lastly, if the
  1701. //                frame has a source frame (it was the root frame of a part
  1702. //                window), we will record the part window bounds so that any
  1703. //                subsequent part windows opened on the source frame will appear
  1704. //                in the same location.
  1705. //------------------------------------------------------------------------------
  1706.  
  1707. SOM_Scope    void
  1708. SOMLINK        SamplePart__DisplayFrameRemoved
  1709.             (
  1710.                 SampleCode_SamplePart*        somSelf,
  1711.                 Environment*                ev,
  1712.                 ODFrame*                    frame
  1713.             )
  1714. {
  1715.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1716.     SampleCode_SamplePartMethodDebug("SamplePart","DisplayFrameRemoved");
  1717.  
  1718.     SOM_TRY
  1719.     
  1720.         CLink*            link;
  1721.         CFrameInfo*        frameInfo;
  1722.         CFrameProxy*    proxy;        
  1723.         
  1724.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  1725.         CHECK_ENV(ev);
  1726.     
  1727.         // Make sure the frame going away does not own any foci. Forgetting
  1728.         // to do this, will cause a "refcounting" error when the frame
  1729.         // is deleted by the draft.
  1730.         _RelinquishAllFoci(somSelf, ev, frame);
  1731.         CHECK_ENV(ev);
  1732.  
  1733.         // If removing a child window, show zoom rects back to source.
  1734.         // NOTE: This has to be done before CleanupDisplayFrame because 
  1735.         // CleanupDisplayFrame will remove the relationship.
  1736.         if ( ODFrame_IsRoot(frame, ev) && CFrameInfo_HasSourceFrame(frameInfo) )
  1737.         {
  1738.             ODWindow* window = ODFrame_AcquireWindow(frame, ev);
  1739.             _ZoomPartWindow(somSelf, ev, CFrameInfo_GetSourceFrame(frameInfo, ev),
  1740.                                     window, kWindowClosing);
  1741.         }
  1742.                 
  1743.         // Clean up the display frame.
  1744.         _CleanupDisplayFrame(somSelf, ev, frame, kFrameRemoved);
  1745.         CHECK_ENV(ev);
  1746.         // Clean up any associated window.
  1747.         _CleanupWindow(somSelf, ev, frame);
  1748.         CHECK_ENV(ev);
  1749.         // Dispose of the frame's runtime state info.
  1750.         ODFrame_SetPartInfo(frame, ev, (ODInfoType) kODNULL);
  1751.         CFrameInfo_Delete(&frameInfo, ev);
  1752.         CHECK_ENV(ev);
  1753.         
  1754.         // Remove the display frame from our collection.
  1755.         for ( link = CLinkedList_First(_fDisplayFrames);
  1756.              CLink_Content(link);
  1757.              link = CLink_Next(link) )
  1758.         {
  1759.             proxy = (CFrameProxy*) CLink_Content(link);
  1760.  
  1761.             if ( ODObjectsAreEqual(ev, CFrameProxy_GetFrame(proxy,ev), frame) )
  1762.             {
  1763.                 // Delete the proxy object and it's contents. The frame's
  1764.                 // refcount will be decremented in the proxy destructor.
  1765.                 link = link->prev;
  1766.                 CLinkedList_Remove(_fDisplayFrames, proxy);
  1767.                 CFrameProxy_Delete(&proxy, ev);
  1768.             }
  1769.             CHECK_ENV(ev);
  1770.         }
  1771.  
  1772.         // Since we maintain a persistent list of weak references to our
  1773.         // display frames, having one removed from the part dirties it.
  1774.         _SetDirty(somSelf, ev);
  1775.         CHECK_ENV(ev);
  1776.     
  1777.     SOM_CATCH_ALL
  1778.         // Alert the user of the problem.
  1779.         _DoDialogBox(somSelf, ev, frame, kErrorBoxID, kErrRemoveFrame);
  1780.         // Change the exception value, so the DocShell doesn't display an
  1781.         // error dialog.
  1782.         ODSetSOMException(ev, kODErrAlreadyNotified, kODNULL);
  1783.     SOM_ENDTRY
  1784. }
  1785.  
  1786. //------------------------------------------------------------------------------
  1787. // Method:        DisplayFrameClosed
  1788. //
  1789. // Description:    This method is called in response to a frame being closed as a
  1790. //                result of the document having been closed by the user.
  1791. //
  1792. //                The part behaves much the same way that it would if a frame were
  1793. //                removed (see above), except that we don't need to cache runtime
  1794. //                information. 
  1795. //------------------------------------------------------------------------------
  1796.  
  1797. SOM_Scope    void
  1798. SOMLINK        SamplePart__DisplayFrameClosed
  1799.             (
  1800.                 SampleCode_SamplePart*        somSelf,
  1801.                 Environment*                ev,
  1802.                 ODFrame*                    frame
  1803.             )
  1804. {
  1805.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1806.     SampleCode_SamplePartMethodDebug("SamplePart","DisplayFrameClosed");
  1807.  
  1808.     SOM_TRY
  1809.  
  1810.         CLink*            link = kODNULL;
  1811.         CFrameInfo*        frameInfo = kODNULL;
  1812.         CFrameProxy*    proxy = kODNULL;        
  1813.         
  1814.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  1815.         CHECK_ENV(ev);
  1816.     
  1817.         // Make sure the frame going away does not own any foci. Forgetting
  1818.         // to do this, will cause a "refcounting" error when the frame
  1819.         // is deleted by the draft.
  1820.         _RelinquishAllFoci(somSelf, ev, frame);
  1821.         CHECK_ENV(ev);
  1822.  
  1823.         // Clean up the display frame.
  1824.         _CleanupDisplayFrame(somSelf, ev, frame, kFrameRemoved);
  1825.         CHECK_ENV(ev);
  1826.         // Clean up any associated window.
  1827.         _CleanupWindow(somSelf, ev, frame);
  1828.         CHECK_ENV(ev);
  1829.         // Dispose of the frame's runtime state info.
  1830.         ODFrame_SetPartInfo(frame, ev, (ODInfoType) kODNULL);
  1831.         CHECK_ENV(ev);
  1832.         CFrameInfo_Delete(&frameInfo, ev);
  1833.         
  1834.         // Remove the display frame from our collection.
  1835.         for ( link = CLinkedList_First(_fDisplayFrames);
  1836.              CLink_Content(link);
  1837.              link = CLink_Next(link) )
  1838.         {
  1839.             // Get the ID of the frame we are going to weakly reference.
  1840.             proxy = (CFrameProxy*) CLink_Content(link);
  1841.             
  1842.             if ( CFrameProxy_GetID(proxy) == ODFrame_GetID(frame, ev) )
  1843.             {
  1844.                 // Release the frame reference, but don't get rid of the
  1845.                 // proxy object because "closed" frames may be reconnected
  1846.                 // before the document is closed.
  1847.                 CFrameProxy_Purge(proxy, ev);
  1848.             }
  1849.             CHECK_ENV(ev);
  1850.         }
  1851.  
  1852.     SOM_CATCH_ALL
  1853.         // Alert the user of the problem.
  1854.         _DoDialogBox(somSelf, ev, frame, kErrorBoxID, kErrRemoveFrame);
  1855.         // Change the exception value, so the DocShell doesn't display an
  1856.         // error dialog.
  1857.         ODSetSOMException(ev, kODErrAlreadyNotified, kODNULL);
  1858.     SOM_ENDTRY
  1859. }
  1860.  
  1861. //------------------------------------------------------------------------------
  1862. // Method:        CleanupDisplayFrame
  1863. // Origin:        SamplePart
  1864. //
  1865. // Description:    This method is called when a frame has been closed or removed.
  1866. //                The method cleans up the references and state information stored
  1867. //                in the CFrameInfo class.
  1868. //------------------------------------------------------------------------------
  1869.  
  1870. SOM_Scope    void  
  1871. SOMLINK        SamplePart__CleanupDisplayFrame
  1872.             (
  1873.                 SampleCode_SamplePart*    somSelf, 
  1874.                 Environment*            ev,
  1875.                 ODFrame*                frame,
  1876.                 ODBoolean                frameRemoved
  1877.             )
  1878. {
  1879.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  1880.     SampleCode_SamplePartMethodDebug("SamplePart","CleanupDisplayFrame");
  1881.  
  1882.     SOM_TRY
  1883.         ODFrame*     sourceFrame = kODNULL;
  1884.         CFrameInfo* sourceFrameInfo = kODNULL;
  1885.         CFrameInfo*    frameInfo = kODNULL;
  1886.         ODError        error = noErr;
  1887.             
  1888.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  1889.         CHECK_ENV(ev);
  1890.  
  1891.         TRY
  1892.             // If we are the root of a child window, we need to notify
  1893.             // our source frame that we are going away.
  1894.             if ( CFrameInfo_HasSourceFrame(frameInfo) )
  1895.             {
  1896.                 sourceFrame = CFrameInfo_GetSourceFrame(frameInfo, ev);
  1897.                 CHECK_ENV(ev);
  1898.                 sourceFrameInfo = (CFrameInfo*) ODFrame_GetPartInfo(sourceFrame, ev);
  1899.                 CHECK_ENV(ev);
  1900.     
  1901.                 if ( frameRemoved )
  1902.                 {
  1903.                     // Invalidate the source frame. We do this because the
  1904.                     // source frame may have a unique display when it has
  1905.                     // been opened into a part window. This forces the
  1906.                     // frame to redraw "not opened".
  1907.                     ODFrame_Invalidate(sourceFrame, ev, kODNULL, kODNULL);
  1908.                     CHECK_ENV(ev);
  1909.                 }
  1910.                 
  1911.                 // Tell the source frame that its dependent is going away.
  1912.                 CFrameInfo_ReleaseDependentFrame(sourceFrameInfo, ev);            
  1913.     
  1914.                 // Release our reference to the source frame.
  1915.                 CFrameInfo_ReleaseSourceFrame(frameInfo, ev);
  1916.     
  1917.                 // If the frame is the root, it is a part window going away
  1918.                 // and we need to notify our source frame that it no longer
  1919.                 // has a part window.
  1920.                 if ( ODFrame_IsRoot(frame, ev) )
  1921.                     CFrameInfo_SetPartWindow(sourceFrameInfo, ev, kODNULL);
  1922.             }
  1923.         CATCH_ALL
  1924.             error = ErrorCode();
  1925.         ENDTRY
  1926.  
  1927.         TRY
  1928.             // If the frame was removed from the document, we need to remove
  1929.             // any child window displaying that frame.
  1930.             if ( frameRemoved )
  1931.             {
  1932.                 // If we have a child window, we need to close it.
  1933.                 ODWindow* window = CFrameInfo_AcquirePartWindow(frameInfo, ev);
  1934.     
  1935.                 if ( window )
  1936.                 {
  1937.                     CFrameInfo_SetPartWindow(frameInfo, ev, kODNULL);
  1938.                     ODWindow_CloseAndRemove(window, ev);
  1939.                 }
  1940.             }
  1941.         CATCH_ALL
  1942.             error = ErrorCode();
  1943.         ENDTRY
  1944.  
  1945.         TRY
  1946.             // If we have dependent frames, we need to notify them that we
  1947.             // are going away.
  1948.         
  1949.             if ( CFrameInfo_HasDependentFrame(frameInfo) )
  1950.             {
  1951.                 CFrameInfo* dependentFrameInfo = kODNULL;
  1952.                 // Get the frame that is dependent on this one. We can safely
  1953.                 // do this because we only reference our own display frames.
  1954.                 ODFrame* dependentFrame =  CFrameInfo_GetDependentFrame(frameInfo, ev);
  1955.                 CHECK_ENV(ev);
  1956.                 dependentFrameInfo = (CFrameInfo*)ODFrame_GetPartInfo(dependentFrame, ev);
  1957.                 CHECK_ENV(ev);
  1958.     
  1959.                 // Tell the dependent frame that its source is going away.
  1960.                 CFrameInfo_ReleaseSourceFrame(dependentFrameInfo, ev);
  1961.                 
  1962.                 // Release our reference to the dependent frame.
  1963.                 CFrameInfo_ReleaseDependentFrame(frameInfo, ev);
  1964.             }
  1965.         CATCH_ALL
  1966.             error = ErrorCode();
  1967.         ENDTRY
  1968.         
  1969.         // If anything went wrong, signal an error.
  1970.         THROW_IF_ERROR(error);
  1971.         
  1972.     SOM_CATCH_ALL
  1973.     SOM_ENDTRY
  1974. }
  1975.  
  1976. //------------------------------------------------------------------------------
  1977. // Method:        AttachSourceFrame
  1978. // Origin:        ODPart
  1979. //
  1980. // Description:    If the part which we are contained in is opened into a part
  1981. //                window, it is required to iterate over its embedded frames and
  1982. //                add new display frames in the part window. After each new
  1983. //                embedded frame is created, this method will be called.
  1984. //
  1985. //                Given all that, and given our lack of interesting
  1986. //                content, we just validate the frame and attach it to its source.
  1987. //------------------------------------------------------------------------------
  1988.  
  1989. SOM_Scope    void
  1990. SOMLINK        SamplePart__AttachSourceFrame
  1991.             (
  1992.                 SampleCode_SamplePart*        somSelf,
  1993.                 Environment*                ev,
  1994.                 ODFrame*                    frame,
  1995.                 ODFrame*                    sourceFrame
  1996.             )
  1997. {
  1998.     SampleCode_SamplePartMethodDebug("SamplePart","AttachSourceFrame");
  1999.  
  2000.     SOM_TRY
  2001.     
  2002.         CFrameInfo* frameInfo = kODNULL;
  2003.         
  2004.         // Tell the new frame about its source.
  2005.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  2006.         CHECK_ENV(ev);
  2007.         CFrameInfo_SetSourceFrame(frameInfo, ev, sourceFrame);
  2008.         CHECK_ENV(ev);
  2009.         
  2010.         // And tell the source about its new dependent.
  2011.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(sourceFrame, ev);
  2012.         CHECK_ENV(ev);
  2013.         CFrameInfo_SetDependentFrame(frameInfo, ev, frame);
  2014.         CHECK_ENV(ev);
  2015.         
  2016.         // In both cases, refcounting of the frame and sourceFrame is
  2017.         // handled by the CFrameInfo class.
  2018.  
  2019.     SOM_CATCH_ALL
  2020.     SOM_ENDTRY
  2021. }
  2022.  
  2023. //------------------------------------------------------------------------------
  2024. // Method:        ViewTypeChanged
  2025. // Origin:        ODPart
  2026. //
  2027. // Description:    This method is called in response to one of our display frame's
  2028. //                viewType field being modified. We call this method on ourselves
  2029. //                when new display frames are added, but it call also be called
  2030. //                when the user changes the view in the "part info" dialog.
  2031. //
  2032. //                The part first loads the appropriate view icons if needed and
  2033. //                then calculates a new "used" shape based on the bounds of the
  2034. //                new view type. If any problems occur while changing the view,
  2035. //                the part defaults back to frame view (the part's default view).
  2036. //------------------------------------------------------------------------------
  2037.  
  2038. SOM_Scope    void
  2039. SOMLINK        SamplePart__ViewTypeChanged
  2040.             (
  2041.                 SampleCode_SamplePart*        somSelf,
  2042.                 Environment*                ev,
  2043.                 ODFrame*                    frame
  2044.             )
  2045. {
  2046.     SampleCode_SamplePartMethodDebug("SamplePart","ViewTypeChanged");
  2047.             
  2048.     SOM_TRY
  2049.     
  2050.         ODShape* newUsedShape = kODNULL;    ODVolatile(newUsedShape);
  2051.  
  2052.         TRY
  2053.             // Change this frame's used shape to match the new view setting.
  2054.             newUsedShape = _CalcNewUsedShape(somSelf, ev, frame);    
  2055.             CHECK_ENV(ev);
  2056.         CATCH_ALL
  2057.             ODSafeReleaseObject(newUsedShape);
  2058.             RERAISE;
  2059.         ENDTRY
  2060.     
  2061.         ODFrame_Invalidate(frame, ev, kODNULL, kODNULL);
  2062.         CHECK_ENV(ev);
  2063.         ODFrame_ChangeUsedShape(frame, ev, newUsedShape, kODNULL);
  2064.         CHECK_ENV(ev);
  2065.         ODFrame_Invalidate(frame, ev, kODNULL, kODNULL);
  2066.         CHECK_ENV(ev);
  2067.         
  2068.         ODReleaseObject(ev, newUsedShape);
  2069.         
  2070.     SOM_CATCH_ALL
  2071.     SOM_ENDTRY
  2072. }
  2073.  
  2074. //------------------------------------------------------------------------------
  2075. // Method:        CalcNewUsedShape
  2076. // Origin:        SamplePart
  2077. //
  2078. // Description:    This method is called in response to one of display frame's view
  2079. //                being changed. The method calculates the appropriate usedShape
  2080. //                for the new view type.
  2081. //------------------------------------------------------------------------------
  2082.  
  2083. SOM_Scope    ODShape*
  2084. SOMLINK        SamplePart__CalcNewUsedShape
  2085.              (
  2086.                 SampleCode_SamplePart*        somSelf,
  2087.                 Environment*                ev,
  2088.                 ODFrame*                    frame
  2089.             )
  2090. {
  2091.     ODShape* usedShape = kODNULL;         
  2092.     ODVolatile(usedShape);
  2093.  
  2094.     SampleCode_SamplePartMethodDebug("SamplePart","CalcNewUsedShape");
  2095.         
  2096.     SOM_TRY
  2097.     
  2098.         RgnHandle     usedRgn;
  2099.         ODTypeToken view;
  2100.     
  2101.         ODVolatile(usedRgn);
  2102.         
  2103.         view = ODFrame_GetViewType(frame, ev);
  2104.         CHECK_ENV(ev);
  2105.         
  2106.         // If the view is "frame", we intentionally return a nil shape;
  2107.         // doing so, will reset the used shape to equal the frame shape.
  2108.     
  2109.         if ( view == gGlobals->fLargeIconView || 
  2110.                 view == gGlobals->fSmallIconView || 
  2111.                 view == gGlobals->fThumbnailView )
  2112.         {
  2113.             TRY
  2114.                 Rect        bounds;
  2115.                 usedRgn = ODNewRgn();
  2116.         
  2117.                 if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  2118.                 {
  2119.                     OSErr    result = noErr;                    
  2120.                     ODSLong    res = BeginUsingLibraryResources();
  2121.     
  2122.                     // Set the bounds rect for the icon size.
  2123.                     SetRect(&bounds, 0, 0,
  2124.                         (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize,
  2125.                         (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize);
  2126.     
  2127.                     // Convert the icon mask into a Region.
  2128.                     result = IconIDToRgn(usedRgn,&bounds,atAbsoluteCenter, kBaseResourceID);
  2129.                     EndUsingLibraryResources(res);
  2130.     
  2131.                     THROW_IF_ERROR(result);
  2132.                 }
  2133.                 else if ( view == gGlobals->fThumbnailView )
  2134.                 {    
  2135.                     PicHandle thumbnail = _GenerateThumbnail(somSelf, ev, frame);
  2136.     
  2137.                     if ( thumbnail )
  2138.                         bounds = (**thumbnail).picFrame;
  2139.                     else
  2140.                         SetRect(&bounds, 0, 0, kODThumbnailSize, kODThumbnailSize);
  2141.                         
  2142.                     RectRgn(usedRgn,&bounds);
  2143.                 }
  2144.                 
  2145.                 usedShape = ODFrame_CreateShape(frame, ev);
  2146.                 ODShape_SetQDRegion(usedShape, ev, usedRgn);
  2147.                 
  2148.             CATCH_ALL
  2149.                 ODSafeReleaseObject(usedShape);
  2150.                 ODDisposeHandle((ODHandle)usedRgn);
  2151.                 usedShape = kODNULL;
  2152.             ENDTRY
  2153.         }
  2154.     SOM_CATCH_ALL
  2155.     SOM_ENDTRY
  2156.     
  2157.     return usedShape;
  2158. }
  2159.  
  2160. //------------------------------------------------------------------------------
  2161. // Method:        UpdateFrame
  2162. // Origin:        SamplePart
  2163. //
  2164. // Description:    This method is called in response to one of our
  2165. //------------------------------------------------------------------------------
  2166.  
  2167. SOM_Scope    void
  2168. SOMLINK        SamplePart__UpdateFrame
  2169.              (
  2170.                 SampleCode_SamplePart*        somSelf,
  2171.                 Environment*                ev,
  2172.                 ODFrame*                    frame,
  2173.                 ODTypeToken                    view,
  2174.                 ODShape*                    usedShape
  2175.             )
  2176. {
  2177.     SampleCode_SamplePartMethodDebug("SamplePart","UpdateFrame");
  2178.  
  2179.     SOM_TRY
  2180.     
  2181.         // Update the frame to have the new view and UsedShape.
  2182.         ODFrame_Invalidate(frame, ev, kODNULL, kODNULL);
  2183.         CHECK_ENV(ev);
  2184.         ODFrame_SetViewType(frame, ev, view);
  2185.         CHECK_ENV(ev);
  2186.         ODFrame_ChangeUsedShape(frame, ev, usedShape, kODNULL);
  2187.         CHECK_ENV(ev);
  2188.         ODFrame_Invalidate(frame, ev, kODNULL, kODNULL);
  2189.         CHECK_ENV(ev);
  2190.     
  2191.     SOM_CATCH_ALL
  2192.         // Failing isn't great, but we can live with it, so don't set ev.
  2193.         ODSetSOMException(ev, noErr, kODNULL);
  2194.     SOM_ENDTRY
  2195. }
  2196.  
  2197. //------------------------------------------------------------------------------
  2198. // Method:        FrameShapeChanged
  2199. // Origin:        ODPart
  2200. //
  2201. // Description:    This method is called in response to a frame's shape being
  2202. //                altered, either by the user or the part we are embedded in.
  2203. //
  2204. //                To keep all attached frames in sync, we need to propogate the
  2205. //                new frame shape the frames dependent on the changed frame. This
  2206. //                is done by observing the display frames stored in the frame info
  2207. //                and calling RequestFrameShape for each.
  2208. //------------------------------------------------------------------------------
  2209.  
  2210. SOM_Scope    void
  2211. SOMLINK        SamplePart__FrameShapeChanged
  2212.             (
  2213.                 SampleCode_SamplePart*        somSelf,
  2214.                 Environment*                ev,
  2215.                 ODFrame*                    frame
  2216.             )
  2217. {
  2218.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  2219.     SampleCode_SamplePartMethodDebug("SamplePart","FrameShapeChanged");
  2220.  
  2221.     SOM_TRY
  2222.         // Adjust the "used" shape for the new frame shape.
  2223.         ODShape* usedShape = _CalcNewUsedShape(somSelf, ev, frame);
  2224.         ODFrame_ChangeUsedShape(frame, ev, usedShape, kODNULL);
  2225.         ODReleaseObject(ev, usedShape);
  2226.         CHECK_ENV(ev);
  2227.     SOM_CATCH_ALL
  2228.     SOM_ENDTRY
  2229. }
  2230.  
  2231. //------------------------------------------------------------------------------
  2232. // Method:        Open
  2233. // Origin:        ODPart
  2234. //
  2235. // Description:    This method is called when OpenDoc, a containing part, or the
  2236. //                active editor would like to open a frame into a seperate window.
  2237. //                If a source frame is passed into this method, the editor is
  2238. //                being asked one of two things. If the frame is the root, we are
  2239. //                being asked to open an existing document. If the frame is not
  2240. //                the root, we are being asked to open a part window. If a source
  2241. //                frame is not specified, the editor is being asked to open a new
  2242. //                window.
  2243. //------------------------------------------------------------------------------
  2244.  
  2245. SOM_Scope    ODID
  2246. SOMLINK        SamplePart__Open
  2247.             (
  2248.                 SampleCode_SamplePart*        somSelf,
  2249.                 Environment*                ev,
  2250.                 ODFrame*                    frame
  2251.             )
  2252. {
  2253.     ODID windowID = kODNULLID;
  2254.  
  2255.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  2256.     SampleCode_SamplePartMethodDebug("SamplePart","Open");
  2257.  
  2258.     SOM_TRY
  2259.         
  2260.         ODWindow*             window = kODNULL;
  2261.         WindowProperties*    windowProperties = kODNULL;
  2262.         CFrameInfo*         frameInfo = kODNULL;
  2263.                 
  2264.         ODVolatile(window);
  2265.         ODVolatile(windowProperties);
  2266.     
  2267.         TRY
  2268.             // Because the frame parameter being passed to us can be one of
  2269.             // three things, we must determine what it is; either the root
  2270.             // frame of a existing document, the source frame for a part
  2271.             // window, or null if we are opening a new document.
  2272.         
  2273.             if ( frame == kODNULL )
  2274.             {
  2275.                 // Calculate the bounding rectangle for a new window
  2276.                 Rect windowRect = _CalcPartWindowSize(somSelf, ev, kODNULL);
  2277.                 CHECK_ENV(ev);
  2278.                 // Get the default setting for a document window.
  2279.                 windowProperties = _GetDefaultWindowProperties(somSelf, ev, kODNULL, &windowRect);
  2280.                 CHECK_ENV(ev);
  2281.                 // Create a Mac Window and register it with OpenDoc.
  2282.                 window = _CreateWindow(somSelf, ev, kODNULL, kODFrameObject, windowProperties);
  2283.                 CHECK_ENV(ev);
  2284.             }
  2285.             else if ( ODFrame_IsRoot(frame, ev) )
  2286.             {
  2287.                 // Get the previously saved settings for the document window.
  2288.                 windowProperties = _GetSavedWindowProperties(somSelf, ev, frame);
  2289.                 CHECK_ENV(ev);
  2290.                 
  2291.                 if ( windowProperties == kODNULL )
  2292.                 {
  2293.                     // Calculate the bounding rectangle for a new window
  2294.                     Rect windowRect = _CalcPartWindowSize(somSelf, ev, frame);
  2295.                     CHECK_ENV(ev);
  2296.                     // Get the default setting for a document window.
  2297.                     windowProperties = _GetDefaultWindowProperties(somSelf, ev, kODNULL, &windowRect);
  2298.                     CHECK_ENV(ev);
  2299.                 }
  2300.     
  2301.                 // Create a Mac Window and register it with OpenDoc.
  2302.                 window = _CreateWindow(somSelf, ev, frame, kODFrameObject, windowProperties);
  2303.                 CHECK_ENV(ev);
  2304.                 
  2305.                 // We release the source frame here because we didn't call
  2306.                 // EndGetWindowProperties and becuase we are done with it.
  2307.                 ODReleaseObject(ev, windowProperties->sourceFrame);
  2308.             }
  2309.             else // frame is a source frame
  2310.             {
  2311.                 window = _AcquireFramesWindow(somSelf, ev, frame);
  2312.                 CHECK_ENV(ev);
  2313.         
  2314.                 if ( window == kODNULL )
  2315.                 {
  2316.                     // Calculate the bounding rectangle for a new window
  2317.                     Rect windowRect = _CalcPartWindowSize(somSelf, ev, frame);
  2318.                     CHECK_ENV(ev);
  2319.                     // Get the default setting for a document window.
  2320.                     windowProperties = _GetDefaultWindowProperties(somSelf, ev, frame, &windowRect);
  2321.                     CHECK_ENV(ev);
  2322.                     // Create a Mac Window and register it with OpenDoc.
  2323.                     window = _CreateWindow(somSelf, ev, frame, kODFrameObject, windowProperties);
  2324.                     CHECK_ENV(ev);
  2325.                     
  2326.                     // Tell the source frame that it is opened in a part window.
  2327.                     frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  2328.                     CFrameInfo_SetPartWindow(frameInfo, ev, window);
  2329.         
  2330.                     _ZoomPartWindow(somSelf, ev, frame, window, kWindowOpening);
  2331.                 }
  2332.             }
  2333.             CHECK_ENV(ev);
  2334.     
  2335.             // Cleanup allocate memory.
  2336.             ODDisposePtr(windowProperties);
  2337.  
  2338.         CATCH_ALL
  2339.             // If we threw early, the source frame's refcount may be too high.
  2340.             if ( windowProperties )
  2341.                 ODSafeReleaseObject(windowProperties->sourceFrame);
  2342.             // Cleanup the created items.
  2343.             ODDisposePtr(windowProperties);
  2344.             RERAISE;
  2345.         ENDTRY
  2346.     
  2347.         TRY
  2348.             // Create the window's root facet.
  2349.             ODWindow_Open(window, ev);
  2350.             CHECK_ENV(ev);
  2351.             // Make the window visible.
  2352.             ODWindow_Show(window, ev);
  2353.             CHECK_ENV(ev);
  2354.             // Activate and select the window.
  2355.             ODWindow_Select(window, ev);
  2356.             CHECK_ENV(ev);
  2357.             
  2358.             // Get window id to return.
  2359.             windowID = (window ? ODWindow_GetID(window, ev) : kODNULLID);
  2360.             ODReleaseObject(ev, window);
  2361.     
  2362.         CATCH_ALL
  2363.             ODSafeReleaseObject(window);
  2364.             RERAISE;
  2365.         ENDTRY
  2366.     
  2367.     SOM_CATCH_ALL
  2368.         windowID = kODNULLID;
  2369.     SOM_ENDTRY
  2370.  
  2371.     return (windowID);
  2372. }
  2373.  
  2374. //------------------------------------------------------------------------------
  2375. // Method:        AcquireFramesWindow
  2376. // Origin:        SamplePart
  2377. //
  2378. // Description:    This method is called by the part when a frame, that has been
  2379. //                previously opened, is being opened again.
  2380. //
  2381. //                The method retrieves the existing window for the frame and
  2382. //                returns it.                
  2383. //------------------------------------------------------------------------------
  2384.  
  2385. SOM_Scope    ODWindow*
  2386. SOMLINK        SamplePart__AcquireFramesWindow
  2387.             (
  2388.                 SampleCode_SamplePart*        somSelf,
  2389.                 Environment*                ev,
  2390.                 ODFrame*                    frame
  2391.             )
  2392. {
  2393.     CFrameInfo* frameInfo = kODNULL;
  2394.     ODWindow*     window = kODNULL;
  2395.  
  2396.     SampleCode_SamplePartMethodDebug("SamplePart","AcquireFramesWindow");
  2397.  
  2398.     frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  2399.     CHECK_ENV(ev);
  2400.     window = CFrameInfo_AcquirePartWindow(frameInfo, ev);
  2401.     CHECK_ENV(ev);
  2402.     
  2403.     return window;
  2404. }
  2405.  
  2406. //-------------------------------------------------------------------------------
  2407. // Method:        CreateWindow
  2408. // Origin:        SamplePart
  2409. //
  2410. // Description:    This method is called by the part when a window needs to be
  2411. //                created for a frame being opened.
  2412. //
  2413. //                The part uses the information passed in windowProperties to 
  2414. //                create the appropriate window. The generated window is
  2415. //                registered with OpenDoc as a new window (RegisterWindow) or as a
  2416. //                window from an existing document (RegisterWindowForFrame).
  2417. //------------------------------------------------------------------------------
  2418.  
  2419. SOM_Scope    ODWindow*
  2420. SOMLINK        SamplePart__CreateWindow
  2421.              (
  2422.                 SampleCode_SamplePart*        somSelf,
  2423.                 Environment*                ev,
  2424.                 ODFrame*                    frame,
  2425.                 ODType                        frameType,
  2426.                 WindowProperties*            windowProperties
  2427.             )
  2428. {
  2429.     ODWindow* window = kODNULL;
  2430.     
  2431.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  2432.     SampleCode_SamplePartMethodDebug("SamplePart","CreateWindow");
  2433.     
  2434.     SOM_TRY
  2435.     
  2436.         ODPlatformWindow    platformWindow    = kODNULL;
  2437.         ODSShort            errMsgNum        = noErr;
  2438.         ODSession*             session         = kODNULL;
  2439.         ODWindowState*        windowState     = kODNULL;
  2440.         ODBoolean             saveWindow        = kODFalse;
  2441.         ODBoolean             shouldDispose    = kODFalse;
  2442.  
  2443.         // Using the name and the calculated rectangle, create a new window.
  2444.         // Note that we are allocating the window record in temp mem using
  2445.         // the OpenDoc memory mgr. This helps reduce app heap usage.
  2446.         // In addition, OpenDoc requires that all new windows be initially hidden
  2447.         // so that it can correctly layer windows/palettes.
  2448.         platformWindow = NewCWindow((Ptr)ODNewPtr(sizeof(WindowRecord), kODNULL),
  2449.                                     &(windowProperties->boundsRect),
  2450.                                     windowProperties->title,
  2451.                                     kODFalse, /* visible */
  2452.                                     windowProperties->procID,
  2453.                                     (WindowPtr)-1L,
  2454.                                     windowProperties->hasCloseBox,
  2455.                                     windowProperties->refCon);
  2456.     
  2457.         TRY
  2458.             if ( platformWindow )
  2459.             {
  2460.                 session = ODGetSessionFromPart(ev,_fSelf);
  2461.                 CHECK_ENV(ev);
  2462.                 windowState = ODSession_GetWindowState(session, ev);
  2463.                 CHECK_ENV(ev);
  2464.                 
  2465.                 // Shoud the window be saved in the document? Yes if the root frame is
  2466.                 // persistent.
  2467.                 saveWindow = (ODISOStrCompare(frameType, kODFrameObject) == 0);
  2468.                 
  2469.                 // Tell the window object that we will be disposing the window record
  2470.                 // when the root frame is closed/removed.
  2471.                 shouldDispose = kODFalse;
  2472.                                     
  2473.                 // Determine whether we are creating a new window (frame is null),
  2474.                 // or opening a previous saved window (frame is valid).
  2475.                 
  2476.                 if ( frame == kODNULL )
  2477.                 {                                
  2478.                     // Tell OpenDoc about it by creating an OpenDoc window object.
  2479.                     window = ODWindowState_RegisterWindow(
  2480.                                     windowState, ev, 
  2481.                                     platformWindow,                    // Macintosh WindowPtr
  2482.                                     frameType,                        // Frame type (Persistent/Non-persistent)
  2483.                                     windowProperties->isRootWindow,    // Is this a document window?
  2484.                                     windowProperties->isResizable,    // Is this window resizeable?
  2485.                                     windowProperties->isFloating,    // Is this window floating?
  2486.                                     saveWindow,                        // Should this window be persistent?
  2487.                                     shouldDispose,                    // (see comment above)
  2488.                                     _fSelf,                            // Part reference to us
  2489.                                     gGlobals->fFrameView,                        // What view should the window have?
  2490.                                     gGlobals->fMainPresentation,                // What presentation should the window have?
  2491.                                     windowProperties->sourceFrame);    // The display frame being opened, if any
  2492.                     CHECK_ENV(ev);
  2493.                 }
  2494.                 else
  2495.                 {
  2496.                     // Tell OpenDoc about it by creating an OpenDoc window object.
  2497.                     window = ODWindowState_RegisterWindowForFrame( 
  2498.                                     windowState, ev, 
  2499.                                     platformWindow,                    // Macintosh WindowPtr
  2500.                                     frame,                             // root frame for window
  2501.                                     windowProperties->isRootWindow,    // Is this a document window?
  2502.                                     windowProperties->isResizable,    // Is this window resizeable?
  2503.                                     windowProperties->isFloating,    // Is this window floating?
  2504.                                     saveWindow,                        // Should this window be persistent?
  2505.                                     shouldDispose,                    // (see comment above)
  2506.                                     windowProperties->sourceFrame);    // The display frame being opened, if any
  2507.                     CHECK_ENV(ev);
  2508.                 }
  2509.             }
  2510.                 
  2511.         CATCH_ALL
  2512.             // Cleanup Macintosh Window.
  2513.             CloseWindow(platformWindow);
  2514.             ODDisposePtr(platformWindow);
  2515.             // Get the right error message for the problem.
  2516.             errMsgNum = (!frame && windowProperties->sourceFrame)
  2517.                                     ? kErrCantOpenPartWindow : kErrCantOpenDocWindow;
  2518.             SetErrorCode(errMsgNum);
  2519.             RERAISE;
  2520.         ENDTRY
  2521.  
  2522.     SOM_CATCH_ALL
  2523.         // Alert the user of the problem.
  2524.         _DoDialogBox(somSelf, ev, frame, kErrorBoxID, ErrorCode());
  2525.         // Change the exception value, so the DocShell doesn't display an
  2526.         // error dialog.
  2527.         ODSetSOMException(ev, kODErrAlreadyNotified, kODNULL);
  2528.     SOM_ENDTRY
  2529.  
  2530.     return window;
  2531. }
  2532.  
  2533. //------------------------------------------------------------------------------
  2534. // Method:        CleanupWindow
  2535. // Origin:        SamplePart
  2536. //
  2537. // Description:    This method is called by the part when a window needs to be
  2538. //                cleaned up for a frame being closed/removed.
  2539. //
  2540. //                The part deallocates the window buffer allocated in the
  2541. //                CreateWindow() method.
  2542. //------------------------------------------------------------------------------
  2543.  
  2544. SOM_Scope    void
  2545. SOMLINK        SamplePart__CleanupWindow
  2546.             (
  2547.                 SampleCode_SamplePart*        somSelf,
  2548.                 Environment*                ev,
  2549.                 ODFrame*                    frame
  2550.             )
  2551. {
  2552.        ODWindow* window = kODNULL;
  2553.     
  2554.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  2555.     SampleCode_SamplePartMethodDebug("SamplePart","CleanupWindow");
  2556.  
  2557.     ODVolatile(window);
  2558.     
  2559.        TRY
  2560.         CFrameInfo*    frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  2561.         CHECK_ENV(ev);
  2562.         if ( CFrameInfo_ShouldDisposeWindow(frameInfo) )
  2563.         {
  2564.             ODPlatformWindow windowPtr = kODNULL;
  2565.  
  2566.             window = ODFrame_AcquireWindow(frame, ev);
  2567.             CHECK_ENV(ev);
  2568.             THROW_IF_NULL(window);
  2569.             
  2570.             windowPtr = ODWindow_GetPlatformWindow(window, ev);
  2571.             CHECK_ENV(ev);
  2572.             CloseWindow(windowPtr);
  2573.             ODDisposePtr(windowPtr);
  2574.             ODReleaseObject(ev, window);
  2575.         }
  2576.     CATCH_ALL
  2577.         _DoDialogBox(somSelf, ev, frame, kErrorBoxID, kErrWindowGone);
  2578.         ODSafeReleaseObject(window);
  2579.         // consume excpetion because it's not fatal.
  2580.     ENDTRY
  2581.  
  2582. }
  2583.  
  2584. //------------------------------------------------------------------------------
  2585. // Method:        GetDefaultWindowProperties
  2586. // Origin:        SamplePart
  2587. //
  2588. // Description:    This method is called by the part when a new window is being
  2589. //                created. The method examines the frame which is being opened
  2590. //                a generates the default window parameters to pass to the
  2591. //                Mac Toolbox.
  2592. //------------------------------------------------------------------------------
  2593.  
  2594. SOM_Scope WindowProperties*  
  2595. SOMLINK SamplePart__GetDefaultWindowProperties
  2596.         (
  2597.             SampleCode_SamplePart *somSelf, 
  2598.             Environment *ev,
  2599.             ODFrame* sourceFrame,
  2600.             Rect* windowRect
  2601.         )
  2602. {
  2603.     WindowProperties* windowProperties = kODNULL;
  2604.     
  2605.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  2606.     SampleCode_SamplePartMethodDebug("SamplePart","GetDefaultWindowProperties");
  2607.         
  2608.     ODVolatile( windowProperties );
  2609.         
  2610.     SOM_TRY
  2611.         ODIText* windowName;
  2612.  
  2613.         windowProperties = (WindowProperties*) ODNewPtr(sizeof(WindowProperties), kODNULL);
  2614.     
  2615.         // Calculate the offset for the window based on the sourceFrame.    
  2616.         if ( sourceFrame )
  2617.             (void)_CalcPartWindowPosition(somSelf, ev, sourceFrame, windowRect);
  2618.         else
  2619.             OffsetRect(windowRect, kALittleNudge,
  2620.                         GetMBarHeight() + kMacWindowTitleBarHeight);    
  2621.         CHECK_ENV(ev);
  2622.     
  2623.         // Set the window bounds based on the calculated rect.
  2624.         windowProperties->boundsRect = *windowRect;
  2625.     
  2626.         // Get the part name to use for the new window.
  2627.         windowName = GetPartName( ev, _fSelf, kSamplePartCategory);
  2628.         
  2629.         // Convert the ODIText into a Pascal string.
  2630.         if (windowName)
  2631.         {
  2632.             GetITextPString(windowName, windowProperties->title);
  2633.             DisposeIText(windowName);
  2634.         }
  2635.                                         
  2636.         // Fill in the other fields of the Window Properties struct.
  2637.         
  2638.         windowProperties->procID = zoomDocProc;
  2639.         windowProperties->hasCloseBox = kODTrue;
  2640.         windowProperties->refCon = (long) kODNULL;
  2641.         windowProperties->wasVisible = kODFalse;
  2642.         windowProperties->isResizable = kODTrue;
  2643.         windowProperties->isFloating = kODFalse;
  2644.         windowProperties->isRootWindow = sourceFrame ? kODFalse : kODTrue;
  2645.         windowProperties->shouldShowLinks = kODFalse;
  2646.         windowProperties->sourceFrame = sourceFrame;
  2647.  
  2648.     SOM_CATCH_ALL
  2649.         ODDisposePtr(windowProperties);
  2650.     SOM_ENDTRY
  2651.         
  2652.     return windowProperties;
  2653. }
  2654.  
  2655. //------------------------------------------------------------------------------
  2656. // Method:        GetSavedWindowProperties
  2657. // Origin:        SamplePart
  2658. //
  2659. // Description:    This method is called by the part to read in saved information
  2660. //                for a window from an existing document.
  2661. //------------------------------------------------------------------------------
  2662.  
  2663. SOM_Scope    WindowProperties*
  2664. SOMLINK        SamplePart__GetSavedWindowProperties
  2665.              (
  2666.                 SampleCode_SamplePart*        somSelf,
  2667.                 Environment*                ev,
  2668.                 ODFrame*                    frame
  2669.             )
  2670. {
  2671.     WindowProperties*    windowProperties = kODNULL;
  2672.  
  2673.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  2674.     SampleCode_SamplePartMethodDebug("SamplePart","GetSavedWindowProperties");
  2675.  
  2676.     ODVolatile( windowProperties );
  2677.  
  2678.     SOM_TRY
  2679.         
  2680.         windowProperties = (WindowProperties*) ODNewPtr(sizeof(WindowProperties), kODNULL);
  2681.     
  2682.         // If we fail to load the window properties from storage, delete
  2683.         // the structure so the calling code will behave appropriately.    
  2684.         if ( BeginGetWindowProperties(ev, frame, windowProperties) )
  2685.         {
  2686.             ODIText*    windowName;
  2687.             RgnHandle     windowRgn;
  2688.             ODBoolean     repositionWindow;
  2689.             Rect         adjustedBounds;
  2690.             
  2691.             // Note: We don't call EndGetWindowProperties because it releases the
  2692.             // source frame, which we will need after this method returns.
  2693.             
  2694.             // Get the part's name to use for the new window.
  2695.             windowName = GetPartName(ev, _fSelf, kSamplePartCategory);
  2696.             // Convert the ODIText into a Pascal string.
  2697.             GetITextPString(windowName, windowProperties->title);
  2698.             DisposeIText( windowName );
  2699.             
  2700.             // Verify the window is still visible on a monitor.
  2701.             
  2702.             windowRgn = ODNewRgn();
  2703.             repositionWindow = kODFalse;
  2704.             
  2705.             // We are only concerned with the window's title bar being
  2706.             // visible, so calcuate the titlebar rect from the current
  2707.             // window bounds.
  2708.             adjustedBounds = windowProperties->boundsRect;
  2709.             adjustedBounds.bottom = adjustedBounds.top;
  2710.             adjustedBounds.top -= kMacWindowTitleBarHeight;
  2711.             
  2712.             // Intersect the monitor's region
  2713.             RectRgn(windowRgn, &adjustedBounds);
  2714.             SectRgn(windowRgn, GetGrayRgn(), windowRgn);
  2715.             
  2716.             if ( !EmptyRgn(windowRgn) )
  2717.             {
  2718.                 // If the visible portion of the window is too small, we need
  2719.                 // to reposition it.
  2720.                 Rect intersectedBounds = (**windowRgn).rgnBBox;
  2721.                 if ( (intersectedBounds.right-intersectedBounds.left < kMinHorzVisPortion) ||
  2722.                         (intersectedBounds.bottom-intersectedBounds.top < kMinVertVisPortion) )
  2723.                     repositionWindow = kODTrue;
  2724.             }
  2725.             else
  2726.             {
  2727.                 // If the window is completely offscreen, we need to reposition it.
  2728.                 repositionWindow = kODTrue;
  2729.             }
  2730.             ODDisposeHandle((ODHandle)windowRgn);
  2731.             
  2732.             // If not, we need to move it so the user can see it.
  2733.             if ( repositionWindow )
  2734.             {
  2735.                 Rect windowRect = (windowProperties->boundsRect);
  2736.                 // Move the window to {0,0} coordinates.
  2737.                 OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
  2738.                 // Now move the window to the default window position.
  2739.                 OffsetRect(&windowRect, kALittleNudge, GetMBarHeight() + kMacWindowTitleBarHeight);
  2740.                 // Save the new window position in our windowProperties.
  2741.                 windowProperties->boundsRect = windowRect;
  2742.             }
  2743.         }
  2744.         else
  2745.         {
  2746.             // If we were unable to re-load window properties, dispose of the
  2747.             // struct.
  2748.             ODDisposePtr(windowProperties);
  2749.         }
  2750.         CHECK_ENV(ev);
  2751.  
  2752.     SOM_CATCH_ALL
  2753.         ODDisposePtr( windowProperties );
  2754.     SOM_ENDTRY
  2755.     
  2756.     return windowProperties;
  2757. }
  2758.  
  2759. //------------------------------------------------------------------------------
  2760. // Method:        CalcPartWindowSize
  2761. // Origin:        SamplePart
  2762. //
  2763. // Description:    This method is called by the part to determine what size a new
  2764. //                window shoud be.
  2765. //------------------------------------------------------------------------------
  2766.  
  2767. SOM_Scope    Rect
  2768. SOMLINK        SamplePart__CalcPartWindowSize
  2769.              (
  2770.                 SampleCode_SamplePart*        somSelf,
  2771.                 Environment*                ev,
  2772.                 ODFrame*                    sourceFrame
  2773.             )
  2774. {
  2775.     const ODSShort kOnePageWidth = 600;
  2776.     
  2777.     Rect windowRect;
  2778.  
  2779.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  2780.     SampleCode_SamplePartMethodDebug("SamplePart","CalcPartWindowSize");
  2781.  
  2782.     SOM_TRY
  2783.         
  2784.         ODRect        frameRect;
  2785.         ODShape*    frameShape;
  2786.         
  2787.         // If a source frame is given, the part is being asked to open one of
  2788.         // its display frames into a part window. Otherwise, we are being opened
  2789.         // as the root frame of the current document and should size the window
  2790.         // accordingly.
  2791.     
  2792.         // Set up the child window's size to be that of the display frame being opened.
  2793.         if ( sourceFrame )
  2794.         {
  2795.             TRY
  2796.                 // Retrieve the fixed point bounding box for the frame.
  2797.                 frameShape = ODFrame_AcquireFrameShape(sourceFrame, ev, kODNULL);
  2798.                 CHECK_ENV(ev);
  2799.                 ODShape_GetBoundingBox(frameShape, ev, &frameRect);
  2800.                 CHECK_ENV(ev);
  2801.                 ODReleaseObject(ev, frameShape);
  2802.                 
  2803.                 // Convert that into a Quickdraw rectangle.
  2804.                 FixedToIntRect(&frameRect, &windowRect);
  2805.             CATCH_ALL
  2806.                 ODSafeReleaseObject(frameShape);
  2807.                 RERAISE;
  2808.             ENDTRY
  2809.         }
  2810.         // Otherwise, just open a large window.
  2811.         else
  2812.         {
  2813.             // (3 * kODLargeIconSize) prevents the window from covering the volume
  2814.             // icons on the desktop which is a violation of Macintosh HI Guidelines.
  2815.     
  2816.             SetRect(&windowRect, 0, 0,
  2817.                       ODQDGlobals.screenBits.bounds.right - (3 * kODLargeIconSize),
  2818.                       ODQDGlobals.screenBits.bounds.bottom
  2819.                           - GetMBarHeight() - kMacWindowTitleBarHeight - kALittleNudge);    
  2820.                     
  2821.             if ( windowRect.right - windowRect.left > kOnePageWidth )
  2822.                 windowRect.right = windowRect.left + kOnePageWidth;
  2823.         }
  2824.         
  2825.     SOM_CATCH_ALL
  2826.     SOM_ENDTRY
  2827.     
  2828.     return windowRect;
  2829. }
  2830.  
  2831. //------------------------------------------------------------------------------
  2832. // Method:        CalcPartWindowPosition
  2833. // Origin:        SamplePart
  2834. //
  2835. // Description:    This method is called by the part to determine where to align
  2836. //                the new window (top left corner of the screen or tiled to a
  2837. //                frame).
  2838. //------------------------------------------------------------------------------
  2839.  
  2840. SOM_Scope    Rect
  2841. SOMLINK        SamplePart__CalcPartWindowPosition
  2842.              (
  2843.                 SampleCode_SamplePart*        somSelf,
  2844.                 Environment*                ev,
  2845.                 ODFrame*                    frame,
  2846.                 Rect*                        partWindowBounds
  2847.             )
  2848. {
  2849.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  2850.     SampleCode_SamplePartMethodDebug("SamplePart","CalcPartWindowPosition");
  2851.  
  2852.     SOM_TRY
  2853.         
  2854.         ODFacet*        activeFacet;
  2855.         ODFrame*        activeFrame;
  2856.         ODCanvas*        canvas;
  2857.         ODRect            bbox;
  2858.         Rect            bounds;
  2859.         ODShape*         frameShape = kODNULL;
  2860.         ODTransform*     windowFrameTransform = kODNULL;
  2861.         ODShape*         boundsShape = kODNULL;
  2862.         
  2863.         ODVolatile(frameShape);
  2864.         ODVolatile(boundsShape);
  2865.         ODVolatile(windowFrameTransform);
  2866.     
  2867.         // We need to know which facet of the frame we are opening to position
  2868.         // the part window. 
  2869.         activeFacet = _GetActiveFacetForFrame(somSelf, ev, frame);
  2870.         CHECK_ENV(ev);
  2871.         
  2872.         // This should never occur, but if it did, it would be fatal.
  2873.         // So we will just pass back the same rectangle.
  2874.         THROW_IF_NULL(activeFacet);
  2875.         
  2876.         // For the purposes of tiling, we need the to know the area of the
  2877.         // document the frame occupies. We do this by getting the bouding
  2878.         // box and offsetting it by the aggregate external window transform
  2879.         // of the facet. 
  2880.         
  2881.         TRY
  2882.             activeFrame = ODFacet_GetFrame(activeFacet, ev);
  2883.             CHECK_ENV(ev);
  2884.             frameShape = ODFrame_AcquireFrameShape(activeFrame, ev, kODNULL);
  2885.             CHECK_ENV(ev);
  2886.             windowFrameTransform = ODFacet_AcquireWindowFrameTransform(activeFacet, ev, kODNULL);
  2887.             CHECK_ENV(ev);
  2888.         CATCH_ALL
  2889.             ODSafeReleaseObject(frameShape);
  2890.             RERAISE;
  2891.         ENDTRY
  2892.         
  2893.         TRY
  2894.             boundsShape = CopyAndRelease(ev, frameShape);
  2895.         
  2896.             // Translate the bounds rect into window coordinates.
  2897.             ODShape_Transform(boundsShape, ev, windowFrameTransform);
  2898.             CHECK_ENV(ev);
  2899.             
  2900.             // Get and convert the bounding box into a QuickDraw rectangle. 
  2901.             ODShape_GetBoundingBox(boundsShape, ev, &bbox);
  2902.             CHECK_ENV(ev);
  2903.             FixedToIntRect(&bbox, &bounds);
  2904.         
  2905.             ODReleaseObject(ev, boundsShape);
  2906.             ODReleaseObject(ev, windowFrameTransform);
  2907.         CATCH_ALL
  2908.             ODSafeReleaseObject(boundsShape);
  2909.             ODSafeReleaseObject(windowFrameTransform);
  2910.             RERAISE;
  2911.         ENDTRY
  2912.         
  2913.         // We then call our method to tile the child window.
  2914.         *partWindowBounds = TilePartWindow(ev, &bounds, partWindowBounds);
  2915.         
  2916.         // Set the port and origin so we can convert the rect to
  2917.         // global Window Mgr coordinates.
  2918.         canvas = ODFacet_GetCanvas(activeFacet, ev);
  2919.         CHECK_ENV(ev);
  2920.         SetPort(ODCanvas_GetQDPort(canvas, ev));
  2921.         SetOrigin(0,-kMacWindowTitleBarHeight);
  2922.         
  2923.         // Convert the local coordinates to global Window Mgr coordinates. 
  2924.         LocalToGlobal((Point*)(&(partWindowBounds->top)));
  2925.         LocalToGlobal((Point*)(&(partWindowBounds->bottom)));
  2926.         
  2927.     SOM_CATCH_ALL
  2928.     SOM_ENDTRY
  2929.     
  2930.     return *partWindowBounds;
  2931. }
  2932.  
  2933. //------------------------------------------------------------------------------
  2934. // Method:        ZoomPartWindow
  2935. // Origin:        SamplePart
  2936. //
  2937. // Description:    This method is called by the part when a frame is being opened
  2938. //                or closed in the case that zooming rectangles should be shown.                
  2939. //------------------------------------------------------------------------------
  2940.  
  2941. SOM_Scope    void
  2942. SOMLINK        SamplePart__ZoomPartWindow
  2943.              (
  2944.                 SampleCode_SamplePart*        somSelf,
  2945.                 Environment*                ev,
  2946.                    ODFrame*                    frame,
  2947.                    ODWindow*                    window,
  2948.                    ODBoolean                    openingWindow
  2949.                )
  2950. {
  2951.     const ODSShort kNumZoomSteps = 12;
  2952.  
  2953.     SOM_Trace("SamplePart","ZoomPartWindow");
  2954.  
  2955.     SOM_TRY
  2956.     
  2957.         Rect frameRect;
  2958.         Rect windowRect;
  2959.         Rect fromRect;
  2960.         Rect toRect;
  2961.  
  2962.         {
  2963.             // We need to know which facet of the frame we are opening to position
  2964.             // the child window.
  2965.             ODFacet* zoomFacet = kODNULL;
  2966.             
  2967.             TRY
  2968.                 zoomFacet = _GetActiveFacetForFrame(somSelf, ev, frame);
  2969.             CATCH_ALL
  2970.             ENDTRY
  2971.             
  2972.             // In case there isn't an active facet for the frame.
  2973.             if ( zoomFacet == kODNULL )
  2974.             {
  2975.                 ODFrameFacetIterator* iter = ODFrame_CreateFacetIterator(frame, ev);
  2976.                 zoomFacet = ODFrameFacetIterator_First(iter, ev);
  2977.                 ODDeleteObject_C(iter);
  2978.             }
  2979.             
  2980.             if ( zoomFacet != kODNULL )
  2981.             {
  2982.                 ODShape*    boundsShape;
  2983.                 ODFrame*    zoomFrame;
  2984.                 ODCanvas*    canvas;
  2985.                 ODRect        bbox;
  2986.                 
  2987.                 // For doing the zoom rects, we need the to know the area of the
  2988.                 // document the frame occupies. We do this by getting the bouding
  2989.                 // box and offsetting it by the aggregate external window transform
  2990.                 // of the facet.
  2991.                 ODTransform* windowFrameTransform =
  2992.                                     ODFacet_AcquireWindowFrameTransform(zoomFacet, ev, kODNULL);
  2993.                 zoomFrame = ODFacet_GetFrame(zoomFacet, ev);
  2994.                 boundsShape = CopyAndRelease(ev, ODFrame_AcquireFrameShape(zoomFrame, ev, kODNULL));
  2995.                 
  2996.                 // Translate the bounds rect into window coordinates.
  2997.                 ODShape_Transform(boundsShape, ev, windowFrameTransform);
  2998.                 
  2999.                 // Get and convert the bounding box into a QuickDraw rectangle.
  3000.                 ODShape_GetBoundingBox(boundsShape, ev, &bbox);
  3001.                 FixedToIntRect(&bbox, &frameRect);
  3002.                     
  3003.                 // Set the port and origin so we can convert the rect to
  3004.                 // global Window Mgr coordinates.
  3005.                 canvas = ODFacet_GetCanvas(zoomFacet, ev); 
  3006.                 SetPort(ODCanvas_GetQDPort(canvas, ev));
  3007.                 SetOrigin(0, 0);
  3008.                 
  3009.                 // Convert the local coordinates to global Window Mgr coordinates.
  3010.                 LocalToGlobal((Point*) &frameRect.top);
  3011.                 LocalToGlobal((Point*) &frameRect.bottom);
  3012.                 
  3013.                 ODReleaseObject(ev, windowFrameTransform);
  3014.                 ODReleaseObject(ev, boundsShape);
  3015.             }
  3016.         }
  3017.         
  3018.         {
  3019.             ODPlatformWindow platformWindow = ODWindow_GetPlatformWindow(window, ev);
  3020.     
  3021.             windowRect = platformWindow->portRect;
  3022.             windowRect.top -= kMacWindowTitleBarHeight;
  3023.             
  3024.             // Set the port and origin so we can convert the rect to
  3025.             // global Window Mgr coordinates.
  3026.             SetPort(platformWindow);
  3027.             SetOrigin(0, 0);
  3028.             
  3029.             // Convert the local coordinates to global Window Mgr coordinates.
  3030.             LocalToGlobal((Point*) &windowRect.top);
  3031.             LocalToGlobal((Point*) &windowRect.bottom);
  3032.         }
  3033.         
  3034.         fromRect = openingWindow ? frameRect  : windowRect;
  3035.         toRect   = openingWindow ? windowRect : frameRect;
  3036.         
  3037.         if ( !openingWindow )
  3038.             ODWindow_Hide(window, ev);
  3039.     
  3040.         ZoomRects(&fromRect, &toRect, kNumZoomSteps, 
  3041.                     openingWindow ? zoomAccelerate : zoomDecelerate);
  3042.     SOM_CATCH_ALL
  3043.     SOM_ENDTRY
  3044. }
  3045.  
  3046. //------------------------------------------------------------------------------
  3047. // Method:        GetActiveFacetForFrame
  3048. // Origin:        SamplePart
  3049. //
  3050. // Description:    This method is called by the part when it needs to know what the
  3051. //                current active facet is.
  3052. //
  3053. //                The part uses this method specifically to find the facet of a
  3054. //                source frame when opening a part window.
  3055. //------------------------------------------------------------------------------
  3056.  
  3057. SOM_Scope    ODFacet*
  3058. SOMLINK        SamplePart__GetActiveFacetForFrame
  3059.              (
  3060.                 SampleCode_SamplePart*        somSelf,
  3061.                 Environment*                ev,
  3062.                 ODFrame*                    frame
  3063.             )
  3064. {
  3065.     ODFacet* facet = kODNULL;
  3066.     
  3067.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  3068.     SampleCode_SamplePartMethodDebug("SamplePart","GetActiveFacetForFrame");
  3069.  
  3070.     SOM_TRY
  3071.  
  3072.         ODFrameFacetIterator*     fiter = kODNULL;
  3073.         ODFacet*                selectedFacet = kODNULL;
  3074.         CFrameInfo*             frameInfo = kODNULL;
  3075.         
  3076.         ODVolatile( facet );
  3077.         
  3078.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  3079.         CHECK_ENV(ev);
  3080.     
  3081.         // If the frame is active, and it should be, get the active facet
  3082.         // from the frame state info.
  3083.         if ( CFrameInfo_IsFrameActive(frameInfo) )
  3084.         {
  3085.             facet = CFrameInfo_GetActiveFacet(frameInfo);
  3086.         }
  3087.         else
  3088.         {
  3089.             // Otherwise, iterate over the display frames looking for one
  3090.             // that has an active facet... there should be at least one.
  3091.             fiter = ODFrame_CreateFacetIterator(frame, ev);
  3092.             CHECK_ENV(ev);
  3093.             
  3094.             for ( selectedFacet = ODFrameFacetIterator_First(fiter, ev);
  3095.                                    ODFrameFacetIterator_IsNotComplete(fiter, ev);
  3096.                   selectedFacet = ODFrameFacetIterator_Next(fiter, ev) )
  3097.             {
  3098.                 if ( ODFacet_IsSelected(selectedFacet, ev) )
  3099.                 {
  3100.                     facet = selectedFacet;
  3101.                     break;
  3102.                 }
  3103.             }
  3104.             ODDeleteObject_C(fiter);
  3105.             CHECK_ENV(ev);
  3106.         }
  3107.         
  3108.         // If there are no active facets anywhere, this method should never
  3109.         // have been called, so signal an error.
  3110.         if ( facet == kODNULL )
  3111.             THROW(kODErrInvalidFrame);
  3112.             
  3113.     SOM_CATCH_ALL
  3114.         facet = kODNULL;
  3115.     SOM_ENDTRY
  3116.     
  3117.     return facet;
  3118. }
  3119.  
  3120. //==============================================================================
  3121. #pragma mark    • Imaging •
  3122. //==============================================================================
  3123.  
  3124. //------------------------------------------------------------------------------
  3125. // Method:        FacetAdded
  3126. // Origin:        ODPart
  3127. //
  3128. // Description:    This method is called when any part adds a facet to
  3129. //                one of our display frames.
  3130. //
  3131. //                The part calls ViewTypeChanged to load the appropriate
  3132. //                resource for display in this facet and then activates
  3133. //                the frame if we are the root part of an active window.
  3134. //------------------------------------------------------------------------------
  3135.  
  3136. SOM_Scope    void
  3137. SOMLINK        SamplePart__FacetAdded
  3138.             (
  3139.                 SampleCode_SamplePart*        somSelf,
  3140.                 Environment*                ev,
  3141.                 ODFacet*                    facet
  3142.             )
  3143. {
  3144.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  3145.     SampleCode_SamplePartMethodDebug("SamplePart","FacetAdded");
  3146.  
  3147.     SOM_TRY
  3148.     
  3149.         ODFrame*     frame        = kODNULL;
  3150.         CFrameInfo* frameInfo     = kODNULL;
  3151.         
  3152.         frame = ODFacet_GetFrame(facet, ev);
  3153.         CHECK_ENV(ev);
  3154.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  3155.         CHECK_ENV(ev);
  3156.     
  3157.         // If a root facet is being added, the frame should be activated when the
  3158.         // window is "selected". This prevents OpenDoc from getting into an
  3159.         // ambiguous state of no part having the selection focus.
  3160.     
  3161.         if ( ODFrame_IsRoot(frame, ev) )
  3162.         {
  3163.             CFrameInfo_SetActiveFacet(frameInfo, facet);
  3164.             CFrameInfo_SetFrameReactivate(frameInfo, kODTrue);
  3165.         }
  3166.         CHECK_ENV(ev);
  3167.     
  3168.         // If a frame had all of its facets removed, the frame would have
  3169.         // hidden any of its part windows. If the frame becomes visible again,
  3170.         // by having a facet added to it, we will "show" the part window for
  3171.         // the frame.
  3172.         
  3173.         if ( (CountFramesFacets(ev, frame) == 1) )
  3174.         {
  3175.             ODWindow* window = CFrameInfo_AcquirePartWindow(frameInfo, ev);
  3176.             CHECK_ENV(ev);
  3177.             
  3178.             if ( window )
  3179.             {
  3180.                 ODWindow_Show(window, ev);
  3181.                 CHECK_ENV(ev);
  3182.             }
  3183.             
  3184.             ODReleaseObject(ev, window);
  3185.         }
  3186.         CHECK_ENV(ev);
  3187.  
  3188.     SOM_CATCH_ALL
  3189.     SOM_ENDTRY
  3190. }
  3191.  
  3192. //------------------------------------------------------------------------------
  3193. // Method:        FacetRemoved
  3194. //
  3195. // Description:    This method is called when any part removes a facet
  3196. //                from one of our display frames.
  3197. //
  3198. //                The part just removes the "active" note from the
  3199. //                appropriate display frame if necessary since this
  3200. //                facet will not be available, nor active, again.
  3201. //------------------------------------------------------------------------------
  3202.  
  3203. SOM_Scope    void
  3204. SOMLINK        SamplePart__FacetRemoved
  3205.             (
  3206.                 SampleCode_SamplePart*        somSelf,
  3207.                 Environment*                ev,
  3208.                 ODFacet*                    facet
  3209.             )
  3210. {
  3211.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  3212.     SampleCode_SamplePartMethodDebug("SamplePart","FacetRemoved");
  3213.  
  3214.     SOM_TRY
  3215.     
  3216.         ODFrame*     frame         = kODNULL;
  3217.         ODFrame*     containingFrame = kODNULL;
  3218.         CFrameInfo* frameInfo     = kODNULL;
  3219.         ODWindow*    window;
  3220.         
  3221.         ODVolatile(window);
  3222.         
  3223.         frame = ODFacet_GetFrame(facet, ev);
  3224.         CHECK_ENV(ev);
  3225.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  3226.         CHECK_ENV(ev);
  3227.         containingFrame = ODFrame_AcquireContainingFrame(frame, ev);
  3228.         CHECK_ENV(ev);
  3229.  
  3230.         TRY
  3231.             // If the facet was the active facet, it can no longer be.
  3232.             if( ODObjectsAreEqual(ev, CFrameInfo_GetActiveFacet(frameInfo), facet) )
  3233.                 CFrameInfo_SetActiveFacet(frameInfo, kODNULL);
  3234.         
  3235.             // If a frame has all of its facets removed, the frame becomes
  3236.             // "hidden". If the frame a part window, the part window should also
  3237.             // be hidden.
  3238.             
  3239.             if ( (CountFramesFacets(ev, frame) == 0) &&
  3240.                     (containingFrame == kODNULL) )
  3241.             {
  3242.                 window = CFrameInfo_AcquirePartWindow(frameInfo, ev);
  3243.                 CHECK_ENV(ev);
  3244.                 
  3245.                 if ( window )
  3246.                 {
  3247.                     ODWindow_Hide(window, ev);
  3248.                     CHECK_ENV(ev);
  3249.                 }
  3250.                 
  3251.                 ODReleaseObject(ev, window);
  3252.             }
  3253.             CHECK_ENV(ev);
  3254.             
  3255.             ODReleaseObject(ev, containingFrame);
  3256.             
  3257.         CATCH_ALL
  3258.             ODSafeReleaseObject(window);
  3259.             ODSafeReleaseObject(containingFrame);
  3260.             RERAISE;
  3261.         ENDTRY
  3262.  
  3263.     SOM_CATCH_ALL
  3264.     SOM_ENDTRY
  3265. }
  3266.  
  3267. //------------------------------------------------------------------------------
  3268. // Method:        Draw
  3269. // Origin:        ODPart
  3270. //
  3271. // Description:    This method is called when a facet of a part's display
  3272. //                frame intersects the invalidated portion of an OpenDoc
  3273. //                window. The invalidShape parameter passed in is the
  3274. //                portion of the facet which has been invalidated.
  3275. //
  3276. //                The part sets up the drawing environment using a
  3277. //                C++ helper class (CFocus) and then calls the
  3278. //                appropriate drawing method based on the frame's
  3279. //                viewType.
  3280. //------------------------------------------------------------------------------
  3281.  
  3282. SOM_Scope    void
  3283. SOMLINK        SamplePart__Draw
  3284.             (
  3285.                 SampleCode_SamplePart*        somSelf,
  3286.                 Environment*                ev,
  3287.                 ODFacet*                    facet,
  3288.                 ODShape*                    invalidShape
  3289.             )
  3290. {
  3291.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  3292.     SampleCode_SamplePartMethodDebug("SamplePart","Draw");
  3293.  
  3294.     SOM_TRY
  3295.         
  3296.         ODFrame*    frame;
  3297.         ODTypeToken view;
  3298.         FocusState    focusState;
  3299.         
  3300.         // Focus the port and origin for drawing in our facet.
  3301.         // Note that this instance of the CFocusDrawingEnv class
  3302.         // is being allocated on the stack. When the execution
  3303.         // leaves the scope of this method, the destructor (which
  3304.         // cleans up the drawing environment) is automatically
  3305.         // called.
  3306.         BeginFocus(ev, &focusState, facet, kODFalse, kODNULL, kODNULL);
  3307.         CHECK_ENV(ev);
  3308.         
  3309.         frame = ODFacet_GetFrame(facet, ev);
  3310.         CHECK_ENV(ev);
  3311.         view = ODFrame_GetViewType(frame, ev);
  3312.         CHECK_ENV(ev);
  3313.         
  3314.         if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  3315.             _DrawIconView(somSelf, ev, facet);
  3316.         else if ( view == gGlobals->fThumbnailView )
  3317.             _DrawThumbnailView(somSelf, ev, facet);
  3318.         else
  3319.             _DrawFrameView(somSelf, ev, facet);
  3320.  
  3321.         // Cleanup the structure created during port focusing. 
  3322.         EndFocus(&focusState);
  3323.  
  3324.     SOM_CATCH_ALL
  3325.     SOM_ENDTRY
  3326. }
  3327.  
  3328. //------------------------------------------------------------------------------
  3329. // Method:        DrawFrameView
  3330. // Origin:        SamplePart
  3331. //
  3332. // Description:    This method is called by the part when the frame being
  3333. //                drawn is in "frame" view.
  3334. //
  3335. //                SamplePart really has not intrisic content. However,
  3336. //                to provide some visual display, we draw the class name
  3337. //                at 80% of the frame's current height using an outlined
  3338. //                font.
  3339. //------------------------------------------------------------------------------
  3340.  
  3341. SOM_Scope    void
  3342. SOMLINK        SamplePart__DrawFrameView
  3343.              (
  3344.                 SampleCode_SamplePart*        somSelf,
  3345.                 Environment*                ev,
  3346.                 ODFacet*                    facet
  3347.             )
  3348. {
  3349.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  3350.     SampleCode_SamplePartMethodDebug("SamplePart","DrawFrameView");
  3351.  
  3352.     SOM_TRY
  3353.  
  3354.         GrafPtr        port;
  3355.         ODFrame*     frame = kODNULL;
  3356.         ODUShort     frameHeight;
  3357.         ODUShort     frameWidth;
  3358.         ODShape*    frameShape;
  3359.  
  3360.         ODVolatile(frameShape);
  3361.                     
  3362.         GetPort(&port);
  3363.         EraseRect(&port->portRect);
  3364.     
  3365.         // If the facet being draw is attached to a source frame in
  3366.         // another window, we need to access the source frame to determine
  3367.         // what size to draw the content.
  3368.     
  3369.         {
  3370.             CFrameInfo* frameInfo = kODNULL;
  3371.             
  3372.             frame = ODFacet_GetFrame(facet, ev);
  3373.             CHECK_ENV(ev);
  3374.             frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  3375.             if ( CFrameInfo_HasSourceFrame(frameInfo) )
  3376.                 frame = CFrameInfo_GetSourceFrame(frameInfo, ev);
  3377.             else
  3378.                 frame = ODFacet_GetFrame(facet, ev);
  3379.             CHECK_ENV(ev);
  3380.         }
  3381.         
  3382.         TRY
  3383.             RgnHandle    frameRgn;
  3384.             ODCanvas*     biasCanvas;
  3385.             
  3386.             ODVolatile(frameShape);
  3387.             
  3388.             // Get the facet's canvas so shapes are returned in the correct
  3389.             // coordinate system.
  3390.             biasCanvas = ODFacet_GetCanvas(facet, ev);
  3391.             CHECK_ENV(ev);
  3392.         
  3393.             // Calculate font height for drawing. 
  3394.             frameShape = ODFrame_AcquireFrameShape(frame, ev, biasCanvas);
  3395.             CHECK_ENV(ev);
  3396.             frameRgn = ODShape_GetQDRegion(frameShape, ev);
  3397.             CHECK_ENV(ev);
  3398.             frameHeight = (**frameRgn).rgnBBox.bottom - (**frameRgn).rgnBBox.top;
  3399.             frameWidth = (**frameRgn).rgnBBox.right - (**frameRgn).rgnBBox.left;
  3400.             ODReleaseObject(ev, frameShape);
  3401.             
  3402.         CATCH_ALL
  3403.             ODSafeReleaseObject(frameShape);
  3404.             RERAISE;
  3405.         ENDTRY    
  3406.             
  3407.         {
  3408.             ODUShort     size;
  3409.             ODUShort     font;
  3410.             Style         face;
  3411.             ODSLong     rfRef;
  3412.             FontInfo    fontInfo;
  3413.             Str63        defaultString;
  3414.  
  3415.             // Save off port chararcteristics so we can restore it later.
  3416.             size = port->txSize;
  3417.             font = port->txFont;
  3418.             face = port->txFace;
  3419.         
  3420.             // Set the font size to almost fill the frame. 
  3421.             TextSize((ODUShort)(frameHeight * 0.8));
  3422.             // Use the default Application font for this script system. 
  3423.             TextFont(1);
  3424.             TextFace(bold + condense);
  3425.             
  3426.             GetFontInfo(&fontInfo);
  3427.             
  3428.             rfRef = BeginUsingLibraryResources();
  3429.             {
  3430.                 PenState penState;
  3431.     
  3432.                 GetPenState(&penState);
  3433.                 
  3434.                 PenNormal();
  3435.                 GetIndString(defaultString, kMenuStringResID, kDefaultContent1ID);
  3436.                 MoveTo((frameWidth / 2) - (StringWidth(defaultString) / 2),
  3437.                             frameHeight - (fontInfo.descent - 2));
  3438.                 DrawString(defaultString);
  3439.                 
  3440.                 // If the part is selected, fill the background with
  3441.                 // the highlight color.
  3442.                 if ( ODFacet_GetHighlight(facet, ev) == kODFullHighlight )
  3443.                 {
  3444.                     UInt8 mode = LMGetHiliteMode();
  3445.                     BitClr(&mode,pHiliteBit);
  3446.                     LMSetHiliteMode(mode);
  3447.                     InvertRect(&port->portRect);
  3448.                 }
  3449.                 
  3450.                 TextMode(srcXor);
  3451.                 TextSize(24);
  3452.                 TextFace(bold + extend);
  3453.         
  3454.                 GetIndString(defaultString, kMenuStringResID, kDefaultContent2ID);
  3455.                 MoveTo((frameWidth / 2) - (StringWidth(defaultString) / 2),
  3456.                             (frameHeight / 2) + 6);
  3457.                 DrawString(defaultString);
  3458.                 
  3459.                 SetPenState(&penState);
  3460.             }
  3461.             EndUsingLibraryResources(rfRef);
  3462.             
  3463.             // Restore port chararcteristics.
  3464.             SetPort(port);
  3465.             port->txSize = size;
  3466.             port->txFont = font;
  3467.             port->txFace = face;
  3468.         }
  3469.  
  3470.     SOM_CATCH_ALL
  3471.     SOM_ENDTRY
  3472. }
  3473.  
  3474. //--------------------------------------------------------------------
  3475. // Method:        DrawIconView
  3476. // Origin:        SamplePart
  3477. //
  3478. // Description:    This method is called by the part when the frame being
  3479. //                drawn is in "standard icon" view.
  3480. //
  3481. //                The part uses the Icon Utilities toolbox manager to
  3482. //                aid in drawing icons in active windows. The Guidelines
  3483. //                require a different appearance for selected icons in
  3484. //                inactive windows, which we do manually.
  3485. //------------------------------------------------------------------------------
  3486.  
  3487. SOM_Scope    void
  3488. SOMLINK        SamplePart__DrawIconView
  3489.              (
  3490.                 SampleCode_SamplePart*        somSelf,
  3491.                 Environment*                ev,
  3492.                 ODFacet*                    facet
  3493.             )
  3494. {
  3495.     SampleCode_SamplePartMethodDebug("SamplePart","DrawIconView");
  3496.  
  3497.     SOM_TRY
  3498.     
  3499.         Rect                iconRect;
  3500.         IconTransformType     transformType = ttNone;
  3501.         CFrameInfo*            frameInfo;
  3502.         ODFrame*            frame;
  3503.         ODTypeToken            viewType;
  3504.         ODWindow*             window;
  3505.         ODSLong             res;
  3506.     
  3507.         frame = ODFacet_GetFrame(facet, ev);
  3508.         viewType = ODFrame_GetViewType(frame, ev);
  3509.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  3510.     
  3511.         // Check to see if the facet is selected
  3512.         if ( ODFacet_GetHighlight(facet, ev) == kODFullHighlight )
  3513.             transformType = ttSelected;
  3514.         CHECK_ENV(ev);
  3515.             
  3516.         // Check to see if the frame has been opened into a part window.
  3517.         window = CFrameInfo_AcquirePartWindow(frameInfo, ev);
  3518.         if ( window && ODWindow_IsShown(window,ev) )
  3519.             transformType |= ttOpen;
  3520.         CHECK_ENV(ev);
  3521.         
  3522.         // Draw the icon.
  3523.         if ( viewType == gGlobals->fLargeIconView )
  3524.             SetRect(&iconRect, 0, 0, kODLargeIconSize, kODLargeIconSize);
  3525.         else // ( viewType == gGlobals->fSmallIconView )
  3526.             SetRect(&iconRect, 0, 0, kODSmallIconSize, kODSmallIconSize);
  3527.     
  3528.         res = BeginUsingLibraryResources();
  3529.             PlotIconID(&iconRect, atAbsoluteCenter, transformType, kBaseResourceID);
  3530.         EndUsingLibraryResources(res);
  3531.  
  3532.     SOM_CATCH_ALL
  3533.     SOM_ENDTRY
  3534. }
  3535.  
  3536. //--------------------------------------------------------------------
  3537. // Method:        DrawThumbnailView
  3538. // Origin:        SamplePart
  3539. //
  3540. // Description:    This method is called by the part when the frame being
  3541. //                drawn is in "thumbnail" view.
  3542. //
  3543. //                The part uses a picture for its thumbnail view because
  3544. //                it has no intrinsic content. A picture resource is
  3545. //                probably not sufficient for parts with real content.
  3546. //------------------------------------------------------------------------------
  3547.  
  3548. SOM_Scope    void
  3549. SOMLINK        SamplePart__DrawThumbnailView
  3550.              (
  3551.                 SampleCode_SamplePart*        somSelf,
  3552.                 Environment*                ev,
  3553.                 ODFacet*                    facet
  3554.             )
  3555. {
  3556.     SampleCode_SamplePartMethodDebug("SamplePart","DrawThumbnailView");
  3557.  
  3558.     SOM_TRY
  3559.     
  3560.         PicHandle thumbnail;
  3561.         Rect bounds;
  3562.         
  3563.         // Create or retrieve a cached thumbnail picture.
  3564.         thumbnail = _GenerateThumbnail(somSelf, ev, ODFacet_GetFrame(facet, ev));
  3565.         
  3566.         bounds = (**thumbnail).picFrame;
  3567.         DrawPicture(thumbnail, &bounds);
  3568.     
  3569.     SOM_CATCH_ALL
  3570.     SOM_ENDTRY
  3571. }
  3572.  
  3573. //--------------------------------------------------------------------
  3574. // Method:        GenerateThumbnail
  3575. // Origin:        SamplePart
  3576. //
  3577. // Description:    This method is called by the part to generate a 
  3578. //                thumbnail view from the current content.
  3579. //
  3580. //                The part has no content, so we merely load a picture.
  3581. //------------------------------------------------------------------- 
  3582.  
  3583. SOM_Scope    PicHandle
  3584. SOMLINK        SamplePart__GenerateThumbnail
  3585.              (
  3586.                 SampleCode_SamplePart*        somSelf,
  3587.                 Environment*                ev,
  3588.                 ODFrame*                    frame
  3589.             )
  3590. {
  3591.     SampleCode_SamplePartMethodDebug("SamplePart","GenerateThumbnail");
  3592.  
  3593.     SOM_TRY
  3594.  
  3595.         if ( gGlobals->fThumbnail == kODNULL )
  3596.         {
  3597.             // In cases where a part has been instantiated from scratch and has no
  3598.             // content (yet), it is appropriate to display a PICT or some graphic
  3599.             // in place of a "real" thumbnail.
  3600.             
  3601.             LoadThumbnail(ev, &gGlobals->fThumbnail);
  3602.         
  3603.             // If we were unable to load the PICT resource for whatever reason
  3604.             // we will default back to a "frame" view and throw the Resource
  3605.             // Manager error as an exception.
  3606.             if ( gGlobals->fThumbnail == kODNULL )
  3607.             {
  3608.                 ODFrame_ChangeViewType(frame, ev, gGlobals->fFrameView);
  3609.                 CHECK_ENV(ev);
  3610.                 
  3611.                 // There is a bug in ResError, when resources are not found,
  3612.                 // which may cause noErr to be returned. If that is the case,
  3613.                 // we throw resNotFound.
  3614.                 THROW_IF_ERROR((ODError)ResError());
  3615.                 THROW(resNotFound);
  3616.             }
  3617.         }
  3618.  
  3619.     SOM_CATCH_ALL
  3620.     SOM_ENDTRY
  3621.         
  3622.     return (PicHandle)gGlobals->fThumbnail;
  3623. }
  3624.  
  3625. //--------------------------------------------------------------------
  3626. // Method:        GeometryChanged
  3627. // Origin:        ODPart
  3628. //
  3629. // Description:    This method is called when the ExternalTransform or
  3630. //                ClipShape of a facet on one this part's display frames
  3631. //                changes.
  3632. //------------------------------------------------------------------- 
  3633.  
  3634. SOM_Scope void  SOMLINK SamplePart__GeometryChanged(SampleCode_SamplePart *somSelf, 
  3635.             Environment     *ev,
  3636.             ODFacet*         facet,
  3637.             ODBoolean         clipShapeChanged,
  3638.             ODBoolean         externalTransformChanged /* unused */ )
  3639. {
  3640.     SampleCode_SamplePartMethodDebug("SamplePart","GeometryChanged");
  3641.  
  3642.     SOM_TRY
  3643.  
  3644.         if ( clipShapeChanged )
  3645.         {
  3646.             // Specifying kODNULL means to invalidate the clipShape (which was
  3647.             // calculated from the usedShape).
  3648.             ODFacet_Invalidate(facet, ev, kODNULL, kODNULL);
  3649.             CHECK_ENV(ev);
  3650.         }
  3651.  
  3652.     SOM_CATCH_ALL
  3653.     SOM_ENDTRY
  3654. }
  3655.  
  3656. //------------------------------------------------------------------------------
  3657. // Method:        HighlightChanged
  3658. // Origin:        ODPart
  3659. //
  3660. // Description:    This method is called when a facet....
  3661. //------------------------------------------------------------------------------
  3662.  
  3663. SOM_Scope    void
  3664. SOMLINK        SamplePart__HighlightChanged
  3665.             (
  3666.                 SampleCode_SamplePart*        somSelf,
  3667.                 Environment*                ev,
  3668.                 ODFacet*                    facet
  3669.             )
  3670. {
  3671.     ODFrame* frame;
  3672.     
  3673.     SampleCode_SamplePartMethodDebug("SamplePart","HighlightChanged");
  3674.     
  3675.     SOM_TRY
  3676.  
  3677.         frame = ODFacet_GetFrame(facet, ev);
  3678.         CHECK_ENV(ev);
  3679.         
  3680.         // The frame view has no "special" drawing characteristics
  3681.         // when opened or selected, so we don't need to update our
  3682.         // content.
  3683.         
  3684.         if ( ODFrame_GetViewType(frame, ev) != gGlobals->fFrameView )
  3685.             ODFrame_Invalidate(frame, ev, kODNULL, kODNULL);
  3686.         CHECK_ENV(ev);
  3687.  
  3688.     SOM_CATCH_ALL
  3689.     SOM_ENDTRY
  3690. }
  3691.  
  3692. //==============================================================================
  3693. #pragma mark    • Activation •
  3694. //==============================================================================
  3695.  
  3696. //------------------------------------------------------------------------------
  3697. // Method:        BeginRelinquishFocus
  3698. // Origin:        ODPart
  3699. //
  3700. // Description:    This method is called when another part (or possibly
  3701. //                ourself) is requesting a focus for one of its display
  3702. //                frames. Returning true means we are willing to give
  3703. //                up the requested focus.
  3704. //
  3705. //                The part willingly gives up any focus unless it is the
  3706. //                modal focus which we don't want to give up until we
  3707. //                are completely done displaying a modal dialog.
  3708. //------------------------------------------------------------------------------
  3709.  
  3710. SOM_Scope    ODBoolean
  3711. SOMLINK        SamplePart__BeginRelinquishFocus
  3712.             (
  3713.                 SampleCode_SamplePart*        somSelf,
  3714.                 Environment*                ev,
  3715.                 ODTypeToken                    focus,
  3716.                 ODFrame*                    ownerFrame, /* unused */
  3717.                 ODFrame*                    proposedFrame
  3718.             )
  3719. {
  3720.     ODBoolean     willRelinquish = kODTrue;
  3721.  
  3722.     SampleCode_SamplePartMethodDebug("SamplePart","BeginRelinquishFocus");
  3723.  
  3724.     SOM_TRY
  3725.         
  3726.         // Another part is trying to put up a Modal dialog while we
  3727.         // are currently displaying ours. Deny the request. 
  3728.         if ( focus == gGlobals->fModalFocus )
  3729.         {
  3730.             ODPart* proposedPart = kODNULL;
  3731.             
  3732.             proposedPart = ODFrame_AcquirePart(proposedFrame, ev);
  3733.             CHECK_ENV(ev);
  3734.             if ( ODObjectsAreEqual(ev, proposedPart, somSelf) == kODFalse )
  3735.                 willRelinquish =  kODFalse;
  3736.             ODReleaseObject(ev, proposedPart);
  3737.         }
  3738.                     
  3739.     SOM_CATCH_ALL
  3740.     SOM_ENDTRY
  3741.  
  3742.     return willRelinquish;
  3743. }
  3744.  
  3745. //------------------------------------------------------------------------------
  3746. // Method:        CommitRelinquishFocus
  3747. // Origin:        ODPart
  3748. //
  3749. // Description:    This method is called when it is actually time to give
  3750. //                up a focus that had been requested by another part (or
  3751. //                possibly ourself).
  3752. //
  3753. //                The part calls its FocusLost method to handle the 
  3754. //                "reliquishing" of the particular focus.
  3755. //------------------------------------------------------------------------------
  3756.  
  3757. SOM_Scope    void
  3758. SOMLINK        SamplePart__CommitRelinquishFocus
  3759.             (
  3760.                 SampleCode_SamplePart*        somSelf,
  3761.                 Environment*                ev,
  3762.                 ODTypeToken                    focus,
  3763.                 ODFrame*                    ownerFrame,
  3764.                 ODFrame*                    proposedFrame /* unused */
  3765.             )
  3766. {
  3767.     SampleCode_SamplePartMethodDebug("SamplePart","CommitRelinquishFocus");
  3768.  
  3769.     SOM_TRY
  3770.     
  3771.         // We agreed to give up our FocusSet and now we are being asked to
  3772.         // do so. 
  3773.         _FocusLost(somSelf, ev, focus, ownerFrame);
  3774.         CHECK_ENV(ev);
  3775.     
  3776.     SOM_CATCH_ALL
  3777.     SOM_ENDTRY
  3778. }
  3779.  
  3780. //------------------------------------------------------------------------------
  3781. // Method:        AbortRelinquishFocus
  3782. // Origin:        ODPart
  3783. //
  3784. // Description:    This method is called when another part (or possibly
  3785. //                ourself) requested a focus for one of its display
  3786. //                frames, but we returned kODFalse from
  3787. //                BeginRelinqishFocus for one, or all, of the requested
  3788. //                focus. At this point, we are being told to resume
  3789. //                ownership of the focus.
  3790. //
  3791. //                The part calls its FocusAcquired method to handle the 
  3792. //                re-"acquisition" of the particular focus.
  3793. //------------------------------------------------------------------------------
  3794.  
  3795. SOM_Scope    void
  3796. SOMLINK        SamplePart__AbortRelinquishFocus
  3797.             (
  3798.                 SampleCode_SamplePart*        somSelf,
  3799.                 Environment*                ev,
  3800.                 ODTypeToken                    focus, /* unused */
  3801.                 ODFrame*                    ownerFrame, /* unused */
  3802.                 ODFrame*                    proposedFrame /* unused */
  3803.             )
  3804. {
  3805.     SampleCode_SamplePartMethodDebug("SamplePart","AbortRelinquishFocus");
  3806.  
  3807.     // Some parts may have suspended some events in the BeginRelinquishFocus
  3808.     // method. If so, they would resume those events here.
  3809. }
  3810.  
  3811. //--------------------------------------------------------------------
  3812. // Method:        FocusAcquired
  3813. // Origin:        ODPart
  3814. //
  3815. // Description:    This method is called when the Arbitrator has
  3816. //                registered us as the "owner" of the particular focus.
  3817. //                This can occur if a focus is requested, or if a focus
  3818. //                is transfered to one of the part's display frames.
  3819. //
  3820. //                The part will request the other foci it needs to be "active". If
  3821. //                the part is successful, we notify ourself to become active.
  3822. //------------------------------------------------------------------------------
  3823.  
  3824. SOM_Scope    void
  3825. SOMLINK        SamplePart__FocusAcquired
  3826.             (
  3827.                 SampleCode_SamplePart*        somSelf,
  3828.                 Environment*                ev,
  3829.                 ODTypeToken                    focus,
  3830.                 ODFrame*                    ownerFrame
  3831.             )
  3832.  
  3833. {
  3834.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  3835.     SampleCode_SamplePartMethodDebug("SamplePart","FocusAcquired");
  3836.  
  3837.     SOM_TRY
  3838.     
  3839.         ODSession*        session;
  3840.         ODArbitrator*     arbitrator;
  3841.         
  3842.         session =  ODGetSessionFromPart(ev, _fSelf);
  3843.         CHECK_ENV(ev);
  3844.         arbitrator = ODSession_GetArbitrator(session, ev);
  3845.         CHECK_ENV(ev);
  3846.     
  3847.         if ( ODArbitrator_RequestFocusSet(arbitrator, ev, gGlobals->fUIFocusSet, ownerFrame) )
  3848.         {
  3849.             _PartActivated(somSelf, ev, ownerFrame);
  3850.             CHECK_ENV(ev);
  3851.         }
  3852.         CHECK_ENV(ev);
  3853.  
  3854.     SOM_CATCH_ALL
  3855.     SOM_ENDTRY
  3856. }
  3857.  
  3858. //------------------------------------------------------------------------------
  3859. // Method:        FocusLost
  3860. // Origin:        ODPart
  3861. //
  3862. // Description:    This method is called when the Arbitrator has
  3863. //                unregistered us as the "owner" of the particular
  3864. //                focus.
  3865. //
  3866. //                The part unmarks the active frame if the selection
  3867. //                focus is lost.
  3868. //------------------------------------------------------------------------------
  3869.  
  3870. SOM_Scope    void
  3871. SOMLINK        SamplePart__FocusLost
  3872.             (
  3873.                 SampleCode_SamplePart*        somSelf,
  3874.                 Environment*                ev,
  3875.                 ODTypeToken                    focus,
  3876.                 ODFrame*                    ownerFrame
  3877.             )
  3878. {
  3879.     SampleCode_SamplePartMethodDebug("SamplePart","FocusLost");
  3880.  
  3881.     SOM_TRY
  3882.  
  3883.         if ( focus == gGlobals->fSelectionFocus )
  3884.         {
  3885.             CFrameInfo* frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(ownerFrame, ev);
  3886.             CFrameInfo_SetFrameActive(frameInfo, kODFalse);
  3887.         }
  3888.  
  3889.     SOM_CATCH_ALL
  3890.     SOM_ENDTRY
  3891. }
  3892.  
  3893. //------------------------------------------------------------------------------
  3894. // Method:        RelinquishAllFoci
  3895. // Origin:        SamplePart
  3896. //
  3897. // Description:    This method is called when a frame is going away. The method
  3898. //                relinquishes all foci the frame owns.
  3899. //------------------------------------------------------------------------------
  3900.  
  3901. SOM_Scope    void  
  3902. SOMLINK        SamplePart__RelinquishAllFoci
  3903.             (
  3904.                 SampleCode_SamplePart*        somSelf, 
  3905.                 Environment*                ev,
  3906.                 ODFrame*                    frame
  3907.             )
  3908. {
  3909.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  3910.     SampleCode_SamplePartMethodDebug("SamplePart","RelinquishAllFoci");
  3911.  
  3912.     SOM_TRY
  3913.  
  3914.         ODSession* session = kODNULL;
  3915.         ODArbitrator* arbitrator = kODNULL;
  3916.         ODFrame* selectionFocusFrame = kODNULL;
  3917.         ODFrame* menuFocusFrame = kODNULL;
  3918.         
  3919.         ODVolatile(selectionFocusFrame);
  3920.         ODVolatile(menuFocusFrame);
  3921.  
  3922.         session =  ODGetSessionFromPart(ev, _fSelf);
  3923.         CHECK_ENV(ev);
  3924.         arbitrator = ODSession_GetArbitrator(session, ev);
  3925.         CHECK_ENV(ev);
  3926.     
  3927.         TRY
  3928.             selectionFocusFrame = ODArbitrator_AcquireFocusOwner(arbitrator, ev, gGlobals->fSelectionFocus);
  3929.             CHECK_ENV(ev);
  3930.             if ( ODObjectsAreEqual(ev, selectionFocusFrame, frame) )
  3931.             {
  3932.                 ODArbitrator_RelinquishFocus(arbitrator, ev, gGlobals->fSelectionFocus, frame);
  3933.                 CHECK_ENV(ev);
  3934.                 _FocusLost(somSelf, ev, gGlobals->fSelectionFocus, frame);
  3935.                 CHECK_ENV(ev);
  3936.             }
  3937.             ODReleaseObject( ev, selectionFocusFrame);
  3938.         CATCH_ALL
  3939.             ODSafeReleaseObject(selectionFocusFrame);
  3940.         ENDTRY
  3941.         
  3942.         TRY
  3943.             menuFocusFrame = ODArbitrator_AcquireFocusOwner(arbitrator, ev, gGlobals->fMenuFocus);
  3944.             CHECK_ENV(ev);
  3945.             if ( ODObjectsAreEqual(ev, menuFocusFrame, frame) )
  3946.             {
  3947.                 ODArbitrator_RelinquishFocus(arbitrator, ev, gGlobals->fMenuFocus, frame);
  3948.                 CHECK_ENV(ev);
  3949.                 _FocusLost(somSelf, ev, gGlobals->fMenuFocus, frame);
  3950.                 CHECK_ENV(ev);
  3951.             }
  3952.             
  3953.             ODReleaseObject( ev, menuFocusFrame );
  3954.         CATCH_ALL
  3955.             ODSafeReleaseObject( menuFocusFrame );
  3956.         ENDTRY
  3957.  
  3958.     SOM_CATCH_ALL
  3959.     SOM_ENDTRY
  3960. }
  3961.  
  3962. //------------------------------------------------------------------------------
  3963. // Method:        PartActivated
  3964. // Origin:        SamplePart
  3965. //
  3966. // Description:    This method is called when the part has successfully acquired
  3967. //                the set of foci which allow it to "run".
  3968. //------------------------------------------------------------------------------
  3969.  
  3970. SOM_Scope     void 
  3971. SOMLINK     SamplePart__PartActivated
  3972.             (    
  3973.                 SampleCode_SamplePart*    somSelf, 
  3974.                 Environment*            ev,
  3975.                 ODFrame*                 frame
  3976.             )
  3977. {
  3978.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  3979.     SampleCode_SamplePartMethodDebug("SamplePart","PartActivated");
  3980.  
  3981.     SOM_TRY
  3982.     
  3983.         CFrameInfo*    frameInfo = kODNULL;
  3984.         
  3985.         // We are required to re-validate the menubar before displaying it because
  3986.         // any part can/could swap the base menubar at any time.
  3987.         if ( ODMenuBar_IsValid(gGlobals->fMenuBar, ev) == kODFalse )
  3988.         {
  3989.             ODSession* session = kODNULL;
  3990.             ODWindowState*    windowState = kODNULL;
  3991.             
  3992.             ODReleaseObject(ev, gGlobals->fMenuBar);
  3993.             session =  ODGetSessionFromPart(ev, _fSelf);
  3994.             CHECK_ENV(ev);
  3995.             windowState = ODSession_GetWindowState(session, ev);
  3996.             CHECK_ENV(ev);
  3997.             gGlobals->fMenuBar = ODWindowState_CopyBaseMenuBar(windowState, ev);
  3998.             CHECK_ENV(ev);
  3999.             
  4000.             // After copying the "new" base menu bar, don't forget to re-install
  4001.             // your part's menus.
  4002.         }
  4003.         CHECK_ENV(ev);
  4004.         
  4005.         // Display our menu bar.
  4006.         ODMenuBar_Display(gGlobals->fMenuBar, ev);
  4007.         CHECK_ENV(ev);
  4008.     
  4009.         // And set our "active" state.
  4010.         frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  4011.         CHECK_ENV(ev);
  4012.         CFrameInfo_SetFrameActive(frameInfo, kODTrue);
  4013.  
  4014.     SOM_CATCH_ALL
  4015.     SOM_ENDTRY
  4016. }
  4017.  
  4018. //------------------------------------------------------------------------------
  4019. // Method:        ActivateFrame
  4020. // Origin:        SamplePart
  4021. //
  4022. // Description:    This method is called by the part when a kODEvtMouseUp
  4023. //                occurs in an inactive frame in an active window, and
  4024. //                when an OpenDoc document comes forward.
  4025. //
  4026. //                The part activates the frame by requesting the
  4027. //                UIFocusSet (created in Initialize) and by calling
  4028. //                FocusAcquired if we were successful. The method
  4029. //                returns true if no problems were encountered as a
  4030. //                signal to the caller that the frame is now "active".
  4031. //------------------------------------------------------------------------------
  4032.  
  4033. SOM_Scope    ODBoolean
  4034. SOMLINK        SamplePart__ActivateFrame
  4035.              (
  4036.                 SampleCode_SamplePart*        somSelf,
  4037.                 Environment*                ev,
  4038.                 ODFrame*                    frame
  4039.             )
  4040. {
  4041.     ODBoolean activated = kODFalse;        
  4042.  
  4043.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  4044.     SampleCode_SamplePartMethodDebug("SamplePart","ActivateFrame");
  4045.         
  4046.     SOM_TRY
  4047.     
  4048.         ODSession* session = kODNULL;
  4049.         ODArbitrator* arbitrator = kODNULL;
  4050.         
  4051.         session = ODGetSessionFromPart(ev,_fSelf);
  4052.         CHECK_ENV(ev);
  4053.         arbitrator = ODSession_GetArbitrator(session, ev);
  4054.         CHECK_ENV(ev);
  4055.     
  4056.         // Request the set of foci necessary to become active. 
  4057.         if ( ODArbitrator_RequestFocusSet(arbitrator, ev, gGlobals->fUIFocusSet,frame) )
  4058.         {
  4059.             _PartActivated(somSelf, ev, frame);
  4060.             CHECK_ENV(ev);
  4061.             // We were able to become active.
  4062.             activated = kODTrue;
  4063.         }
  4064.         CHECK_ENV(ev);
  4065.  
  4066.     SOM_CATCH_ALL
  4067.         activated =  kODFalse;
  4068.     SOM_ENDTRY
  4069.  
  4070.     return activated;
  4071. }
  4072.  
  4073. //--------------------------------------------------------------------
  4074. // Method:        WindowActivating
  4075. // Origin:        SamplePart
  4076. //
  4077. // Description:    This method is called by the part when a process
  4078. //                switch event (kODEvtOS) occurs.
  4079. //
  4080. //                The part records the active frame, if any of the
  4081. //                display frames were active, so that the frame can be
  4082. //                re-activated when the document is switched into the
  4083. //                foreground.
  4084. //------------------------------------------------------------------- 
  4085.  
  4086. SOM_Scope    void
  4087. SOMLINK        SamplePart__WindowActivating
  4088.              (
  4089.                 SampleCode_SamplePart*        somSelf,
  4090.                 Environment*                ev,
  4091.                 ODFrame*                    frame,
  4092.                 ODBoolean                    activating
  4093.             )
  4094. {
  4095.     SampleCode_SamplePartMethodDebug("SamplePart","WindowActivating");
  4096.  
  4097.     SOM_TRY
  4098.  
  4099.         CFrameInfo* frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  4100.         CHECK_ENV(ev);
  4101.         
  4102.         // The window is being activated and we had the selection focus when
  4103.         // the window was deactivated, so request it again. 
  4104.         if ( activating && CFrameInfo_FrameNeedsReactivating(frameInfo) )
  4105.         {
  4106.             _ActivateFrame(somSelf, ev, frame);
  4107.             CHECK_ENV(ev);
  4108.             
  4109.             CFrameInfo_SetFrameReactivate(frameInfo, kODFalse);
  4110.         }
  4111.         // The window is being deactivated and we have the active part.
  4112.         // So give up our foci and remind ourselves that we need to request
  4113.         // the focus when the window is reactivated. 
  4114.         else if ( !activating && CFrameInfo_IsFrameActive(frameInfo) )
  4115.         {
  4116.             CFrameInfo_SetFrameReactivate(frameInfo, kODTrue);
  4117.         }
  4118.  
  4119.     SOM_CATCH_ALL
  4120.     SOM_ENDTRY
  4121. }
  4122.  
  4123. //==============================================================================
  4124. #pragma mark    • Event Handling •
  4125. //==============================================================================
  4126.  
  4127. //------------------------------------------------------------------------------
  4128. // Method:        HandleEvent
  4129. // Origin:        ODPart
  4130. //
  4131. // Description:    The method is called when an event, which falls into
  4132. //                the category of an owned focus, occurs. The two
  4133. //                exceptions to this are "mouse movement" events and 
  4134. //                embedded frame events, which can occur when a part
  4135. //                owns no foci.
  4136. //
  4137. //                The part returns true if the event was handled.
  4138. //------------------------------------------------------------------------------
  4139.  
  4140. SOM_Scope    ODBoolean
  4141. SOMLINK        SamplePart__HandleEvent
  4142.             (
  4143.                 SampleCode_SamplePart*        somSelf,
  4144.                 Environment*                ev,
  4145.                 ODEventData*                event,
  4146.                 ODFrame*                    frame,
  4147.                 ODFacet*                    facet,
  4148.                 ODEventInfo*                eventInfo)
  4149. {
  4150.     ODBoolean eventHandled = kODFalse;
  4151.  
  4152.     SampleCode_SamplePartMethodDebug("SamplePart","HandleEvent");
  4153.     
  4154.     SOM_TRY
  4155.     
  4156.         // Event handling is basically the same as standard Macintosh applications,
  4157.         // except that the events have been renamed for cross-platform compatability. 
  4158.         
  4159.         switch ( event->what ) {
  4160.             case kODEvtMouseDown:
  4161.             case kODEvtMouseUp:
  4162.                 eventHandled = _HandleMouseEvent(somSelf, ev, event, facet, eventInfo);
  4163.                 CHECK_ENV(ev);
  4164.                 break;
  4165.                 
  4166.             case kODEvtMenu:
  4167.                 eventHandled = _HandleMenuEvent(somSelf, ev, event, frame);
  4168.                 CHECK_ENV(ev);
  4169.                 break;
  4170.                 
  4171.             case kODEvtActivate:
  4172.                 // We are being notified that a window we are display in has
  4173.                 // just been de/activated (un/hilighted). 
  4174.                 _WindowActivating(somSelf, ev, frame, (event->modifiers & activeFlag ));
  4175.                 CHECK_ENV(ev);
  4176.                 eventHandled = kODTrue;
  4177.                 break;
  4178.         
  4179.             case kODEvtMouseEnter:
  4180.             case kODEvtMouseLeave:
  4181.                 SetCursor(&(ODQDGlobals.arrow));
  4182.                 eventHandled = kODTrue;
  4183.                 break;
  4184.     
  4185.             case kODEvtMouseWithin:
  4186.                 eventHandled = kODTrue;
  4187.                 break;
  4188.     
  4189.             // Other events a part might handle
  4190.             case kODEvtNull:
  4191.             case kODEvtMouseDownEmbedded:
  4192.             case kODEvtMouseUpEmbedded:
  4193.             case kODEvtMouseDownBorder:
  4194.             case kODEvtMouseUpBorder:
  4195.             case kODEvtWindow:
  4196.             case kODEvtKeyDown:
  4197.             case kODEvtKeyUp:
  4198.             case kODEvtAutoKey:
  4199.             case kODEvtDisk:
  4200.             case kODEvtOS:
  4201.             
  4202.             default:
  4203.                 break;
  4204.         }
  4205.     
  4206.     SOM_CATCH_ALL
  4207.         eventHandled = kODFalse;
  4208.     SOM_ENDTRY
  4209.  
  4210.     return eventHandled;
  4211. }
  4212.  
  4213. //------------------------------------------------------------------------------
  4214. // Method:        AdjustMenus
  4215. // Origin:        ODPart
  4216. //
  4217. // Description:    This method is called when a kODEvtMouseDown event
  4218. //                occurs in the menubar and the part owns the "menu"
  4219. //                focus.
  4220. //
  4221. //                The part enables the appropriate items for its current
  4222. //                state and updates the menu items to reflect this
  4223. //                editor.
  4224. //------------------------------------------------------------------------------
  4225.  
  4226. SOM_Scope    void
  4227. SOMLINK        SamplePart__AdjustMenus
  4228.             (
  4229.                 SampleCode_SamplePart*        somSelf,
  4230.                 Environment*                ev,
  4231.                 ODFrame*                    frame
  4232.             )
  4233. {
  4234.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  4235.     SampleCode_SamplePartMethodDebug("SamplePart","AdjustMenus");
  4236.  
  4237.     SOM_TRY
  4238.     
  4239.         ODSession*         session = kODNULL;
  4240.         ODArbitrator*     arbitrator = kODNULL;
  4241.         ODWindowState*    windowState = kODNULL;
  4242.         ODIText*        menuItem = kODNULL;
  4243.         ODFrame*         menuOwner = kODNULL;
  4244.         
  4245.         session = ODGetSessionFromPart(ev,_fSelf);
  4246.         CHECK_ENV(ev);
  4247.         
  4248.         // The menubar object always calls the root part's AdjustMenus method before
  4249.         // calling the menu focus owner's. Because of this, we need to validate the
  4250.         // menubar in the case where we are the root part.
  4251.         if ( ODFrame_IsRoot(frame, ev) )
  4252.         {
  4253.             // We are required to re-validate the menubar before displaying it because
  4254.             // any part can/could swap the base menubar at any time.
  4255.             if ( ODMenuBar_IsValid(gGlobals->fMenuBar, ev) == kODFalse )
  4256.             {
  4257.                 ODReleaseObject(ev, gGlobals->fMenuBar);
  4258.                 windowState = ODSession_GetWindowState(session, ev);
  4259.                 CHECK_ENV(ev);
  4260.                 gGlobals->fMenuBar = ODWindowState_CopyBaseMenuBar(windowState, ev);
  4261.                 CHECK_ENV(ev);
  4262.                 
  4263.                 // After copying the "new" base menu bar, don't forget to re-install
  4264.                 // your part's menus.
  4265.             }
  4266.             CHECK_ENV(ev);
  4267.         }        
  4268.         CHECK_ENV(ev);
  4269.  
  4270.         // Enable the "View As Window" command if the frame is not the root
  4271.         // frame of the window. 
  4272.         ODMenuBar_EnableCommand(gGlobals->fMenuBar, ev, kODCommandViewAsWin, !ODFrame_IsRoot(frame, ev));
  4273.         CHECK_ENV(ev);
  4274.     
  4275.         TRY
  4276.             arbitrator = ODSession_GetArbitrator(session, ev);
  4277.             menuOwner = ODArbitrator_AcquireFocusOwner(arbitrator, ev, gGlobals->fMenuFocus);
  4278.     
  4279.             // There is no need to load a resource, create an ODIText object, set the menubar,
  4280.             // and cleanup, if we don't own the menu focus.
  4281.             if ( ODObjectsAreEqual(ev, frame, menuOwner) )
  4282.             {
  4283.                 Str63         text;
  4284.                 // Get the "about" string from our library's resources.
  4285.                 // (note: ODGetIndString focuses the resource fork for us)
  4286.                 ODGetIndString(text, kMenuStringResID, kAboutTextID);
  4287.                 // Create an IText object to pass into the menubar.
  4288.                 menuItem = CreateITextPString(gGlobals->fEditorsScript, gGlobals->fEditorsLanguage, (StringPtr)&text);
  4289.                 ODMenuBar_SetItemString(gGlobals->fMenuBar, ev, kODCommandAbout, menuItem);
  4290.                 DisposeIText(menuItem);
  4291.                 CHECK_ENV(ev);
  4292.             }
  4293.             ODReleaseObject(ev, menuOwner);
  4294.             
  4295.         CATCH_ALL
  4296.             ODSafeReleaseObject(menuOwner);
  4297.         ENDTRY
  4298.  
  4299.     SOM_CATCH_ALL
  4300.     SOM_ENDTRY
  4301. }
  4302.  
  4303. //------------------------------------------------------------------------------
  4304. // Method:        HandleMenuEvent
  4305. // Origin:        SamplePart
  4306. //
  4307. // Description:    This method is called by the part when a menu event is
  4308. //                received.
  4309. //
  4310. //                Using the menu bar object, we determine what the menu
  4311. //                command is, and call the appropriate method to handle
  4312. //                it.
  4313. //------------------------------------------------------------------------------
  4314.  
  4315. SOM_Scope    ODBoolean
  4316. SOMLINK        SamplePart__HandleMenuEvent
  4317.             (
  4318.                 SampleCode_SamplePart*        somSelf,
  4319.                 Environment*                ev,
  4320.                 ODEventData*                event,
  4321.                 ODFrame*                    frame
  4322.             )
  4323. {
  4324.     ODBoolean eventHandled = kODTrue;            
  4325.  
  4326.     SampleCode_SamplePartMethodDebug("SamplePart","HandleMenuEvent");
  4327.  
  4328.     SOM_TRY
  4329.     
  4330.         ODULong        menuResult    = event->message;
  4331.         ODUShort    menu        = HiWord(menuResult);
  4332.         ODUShort    item        = LoWord(menuResult);
  4333.     
  4334.         switch( ODMenuBar_GetCommand(gGlobals->fMenuBar, ev, menu, item) ) {
  4335.     
  4336.             case kODCommandAbout:    
  4337.                     _DoDialogBox(somSelf, ev, frame, kAboutBoxID, 0);
  4338.                     CHECK_ENV(ev);
  4339.                     break;
  4340.         
  4341.             case kODCommandViewAsWin:
  4342.                     SamplePart__Open(somSelf, ev, frame);
  4343.                     CHECK_ENV(ev);
  4344.                     break;
  4345.     
  4346.             // Other commands a part might handle. 
  4347.             case kODCommandOpen:
  4348.             case kODCommandInsert:
  4349.             case kODCommandPageSetup:
  4350.             case kODCommandPrint:
  4351.             case kODCommandUndo:
  4352.             case kODCommandRedo:
  4353.             case kODCommandCut:
  4354.             case kODCommandCopy:
  4355.             case kODCommandPaste:
  4356.             case kODCommandPasteAs:
  4357.             case kODCommandClear:
  4358.             case kODCommandSelectAll:
  4359.             case kODCommandGetPartInfo:
  4360.             case kODCommandPreferences:
  4361.     
  4362.             default:
  4363.                 eventHandled = kODFalse;
  4364.         }
  4365.         CHECK_ENV(ev);
  4366.     
  4367.     SOM_CATCH_ALL
  4368.         eventHandled = kODFalse;
  4369.     SOM_ENDTRY
  4370.             
  4371.     return eventHandled;
  4372. }
  4373.  
  4374. //------------------------------------------------------------------------------
  4375. // Method:        HandleMouseEvent
  4376. // Origin:        SamplePart
  4377. //
  4378. // Description:    This method is called by the part when a mouse event
  4379. //                is recieved.
  4380. //
  4381. //                A typical part would determine the event type(up/down)
  4382. //                and respond appropriately, but we have no "real"
  4383. //                content model, so we activate the part as appropriate
  4384. //                and call a generic method to handle the event.
  4385. //
  4386. // Remember:    When a frame is inactive, the first mouse up event
  4387. //                should activate it; inactive frames do not recieve
  4388. //                kODEvtMouseDown events.
  4389. //------------------------------------------------------------------------------
  4390.  
  4391. SOM_Scope    ODBoolean
  4392. SOMLINK        SamplePart__HandleMouseEvent
  4393.             (
  4394.                 SampleCode_SamplePart*        somSelf,
  4395.                 Environment*                ev,
  4396.                 ODEventData*                event,
  4397.                 ODFacet*                    facet,
  4398.                 ODEventInfo*                eventInfo
  4399.             )
  4400. {
  4401.     SampleCode_SamplePartMethodDebug("SamplePart","HandleMouseEvent");
  4402.  
  4403.     SOM_TRY
  4404.         
  4405.         // If the facet parameter is invalid, the mousedown occurred outside the
  4406.         // bounds of a Modal window, otherwise it should be treated normally. 
  4407.         
  4408.         if ( facet != kODNULL )
  4409.         {
  4410.             if ( event->what == kODEvtMouseUp )
  4411.             {
  4412.                 ODWindow* window = ODFacet_GetWindow(facet, ev);
  4413.                 CHECK_ENV(ev);
  4414.                 
  4415.                 // Activate inactive windows on the first mouse up/down event.
  4416.                 if ( !ODWindow_IsActive(window, ev) )
  4417.                 {
  4418.                     ODWindow_Select(window, ev);
  4419.                     CHECK_ENV(ev);
  4420.                 }
  4421.                 // Activate the frame (if needed) on all mouse up/down events.
  4422.                 else
  4423.                 {
  4424.                     CFrameInfo* frameInfo = kODNULL;
  4425.                     // Get our state information from the PartInfo of the frame. 
  4426.                     ODFrame* frame = ODFacet_GetFrame(facet, ev);
  4427.                     CHECK_ENV(ev);
  4428.                     frameInfo = (CFrameInfo*) ODFrame_GetPartInfo(frame, ev);
  4429.         
  4430.                     // If this frame is not the active one, activate it by requesting
  4431.                     // the appropriate foci. 
  4432.                     
  4433.                     if ( !CFrameInfo_IsFrameActive(frameInfo) )
  4434.                     {
  4435.                         if ( _ActivateFrame(somSelf, ev, frame) )
  4436.                         {
  4437.                             // Keep track of which facet was the last active for positioning
  4438.                             // part windows.
  4439.                             CFrameInfo_SetActiveFacet(frameInfo, facet);
  4440.                         }
  4441.                         else
  4442.                             // We were unable to acquire the necessary focus and activate it. 
  4443.                             return kODFalse;
  4444.                             
  4445.                         CHECK_ENV(ev);
  4446.                     }
  4447.                 }
  4448.                 CHECK_ENV(ev);
  4449.             }
  4450.             else if  ( event->what == kODEvtMouseDown )                
  4451.             {
  4452.                 Point where;
  4453.     
  4454.                 // Get the localized mouse coordinates from the Event Info.
  4455.                 where.h = FixedToInt(eventInfo->where.x);
  4456.                 where.v = FixedToInt(eventInfo->where.y);
  4457.             
  4458.                 // Handle the mouse down event.
  4459.                 _DoMouseEvent(somSelf, ev, facet, &where);
  4460.                 CHECK_ENV(ev);
  4461.             }
  4462.         }
  4463.         else
  4464.         {
  4465.             // User clicked outside the bounds of a Modal window, though we actually
  4466.             // never display one. 
  4467.             
  4468.             SysBeep(1);
  4469.         }
  4470.     
  4471.     SOM_CATCH_ALL
  4472.     SOM_ENDTRY
  4473.     
  4474.     return kODTrue;
  4475. }
  4476.  
  4477. //------------------------------------------------------------------------------
  4478. // Method:        DoMouseEvent
  4479. // Origin:        SamplePart
  4480. //
  4481. // Description:    This method is called by the part to handle mouse
  4482. //                events.
  4483. //------------------------------------------------------------------------------
  4484.  
  4485. SOM_Scope    void
  4486. SOMLINK        SamplePart__DoMouseEvent
  4487.             (
  4488.                 SampleCode_SamplePart*        somSelf,
  4489.                 Environment*                ev,
  4490.                 ODFacet*                    facet,  /* unused */
  4491.                 Point*                        where /* unused */
  4492.             )
  4493. {
  4494.     SampleCode_SamplePartMethodDebug("SamplePart","DoMouseEvent");
  4495.     
  4496.     // If you part allows selections or a lasso tool, this is where you
  4497.     // would handle those events. This is also where you would handle
  4498.     // program controlled buttons or controls.
  4499. }
  4500.  
  4501. //--------------------------------------------------------------------
  4502. // Method:        DoDialogBox
  4503. // Origin:        SamplePart
  4504. //
  4505. // Description:    This method is called by the part when a dialog needs to be
  4506. //                displayed (ie. the About Box). If a valid error number is passed
  4507. //                in, an error dialog will be displayed.
  4508. //------------------------------------------------------------------- 
  4509.  
  4510. SOM_Scope    void
  4511. SOMLINK        SamplePart__DoDialogBox
  4512.              (
  4513.                 SampleCode_SamplePart*        somSelf,
  4514.                 Environment*                ev,
  4515.                 ODFrame*                    frame,
  4516.                 ODSShort                    dialogID,
  4517.                 ODUShort                    errorNumber
  4518.             )
  4519. {
  4520.     SampleCode_SamplePartData *somThis = SampleCode_SamplePartGetData(somSelf);
  4521.     SampleCode_SamplePartMethodDebug("SamplePart","DoAboutBox");
  4522.  
  4523.     SOM_TRY
  4524.             
  4525.         CFrameProxy*    proxy;
  4526.         ODFrame*         focusFrame = frame;
  4527.         CLink*            link;
  4528.         ODSession*        session;
  4529.         ODArbitrator*    arbitrator;
  4530.         
  4531.         // If the calling method does not have a frame available to it, we need to
  4532.         // locate a frame to use for requesting the modal focus. Find the first valid
  4533.         // frame in our display frames list.
  4534.         if ( focusFrame == kODNULL )
  4535.         {
  4536.             for ( link = CLinkedList_First(_fDisplayFrames);
  4537.                  CLink_Content(link);
  4538.                  link = CLink_Next(link) )
  4539.             {
  4540.                 proxy = (CFrameProxy*) CLink_Content(link);
  4541.                 if (CFrameProxy_FrameIsLoaded(proxy, ev))
  4542.                     focusFrame = CFrameProxy_GetFrame(proxy,ev);
  4543.                 CHECK_ENV(ev);
  4544.                 if ( focusFrame ) break;
  4545.             }
  4546.         }
  4547.         
  4548.         // Our About box is modal so we must request the Modal focus to prevent
  4549.         // multiple modal dialogs being displayed simultaneously. 
  4550.         
  4551.         session = ODGetSessionFromPart(ev,_fSelf);
  4552.         CHECK_ENV(ev);
  4553.         arbitrator = ODSession_GetArbitrator(session, ev);
  4554.         CHECK_ENV(ev);
  4555.         
  4556.         if ( ODArbitrator_RequestFocus(arbitrator, ev, gGlobals->fModalFocus,frame) )
  4557.         {
  4558.             DialogPtr    dialog;
  4559.             ODSShort    itemHit;
  4560.             ODSLong     rfRef;
  4561.     
  4562.             // Dim the frontmost document window. 
  4563.             ODWindowState* windowState = ODSession_GetWindowState(session, ev);
  4564.             ODWindowState_DeactivateFrontWindows(windowState, ev);
  4565.             CHECK_ENV(ev);
  4566.                     
  4567.             rfRef = BeginUsingLibraryResources();
  4568.             {            
  4569.                 dialog = GetNewDialog(dialogID, kODNULL, (WindowPtr) -1L);
  4570.                 
  4571.                 if ( dialog )
  4572.                 {
  4573.                     if ( errorNumber > 0 )
  4574.                     {
  4575.                         Handle    itemHandle;
  4576.                         Rect    itemRect;
  4577.                         short    itemType;
  4578.                         Str255    errStr;
  4579.                         
  4580.                         GetIndString(errStr, kErrorStringResID, errorNumber);
  4581.                         GetDialogItem(dialog, kErrStrFieldID, &itemType, &itemHandle, &itemRect);
  4582.                         SetDialogItemText(itemHandle, errStr);
  4583.                         
  4584.                         // We don't need the cancel button for an error dialog.
  4585.                         HideDialogItem(dialog, cancel);
  4586.     
  4587.                         SetDialogDefaultItem(dialog, ok);
  4588.                     }
  4589.                     
  4590.                     SetCursor(&ODQDGlobals.arrow);
  4591.                     ShowWindow(dialog);
  4592.                     ModalDialog(kODNULL, &itemHit);
  4593.                     DisposeDialog(dialog);
  4594.                 }
  4595.                 else
  4596.                 {
  4597.                     // Could not load About box dialog... something is amiss. 
  4598.                     SysBeep(2);
  4599.                 }
  4600.             }
  4601.             EndUsingLibraryResources(rfRef);
  4602.             
  4603.             // Inform the Arbitrator that we no longer require the Modal focus. 
  4604.             ODArbitrator_RelinquishFocus(arbitrator, ev, gGlobals->fModalFocus,frame);
  4605.             CHECK_ENV(ev);
  4606.             
  4607.             // Hilite the frontmost document window.
  4608.             ODWindowState_ActivateFrontWindows(windowState, ev);
  4609.             CHECK_ENV(ev);
  4610.         }
  4611.         else
  4612.             // If we can't get the modal focus, then another modal dialog is
  4613.             // already being displayed. 
  4614.             SysBeep(2);
  4615.         CHECK_ENV(ev);
  4616.         
  4617.     SOM_CATCH_ALL
  4618.     SOM_ENDTRY
  4619. }
  4620.  
  4621.  
  4622. //==============================================================================
  4623. #pragma mark    • Stubbed Methods •
  4624. //==============================================================================
  4625.  
  4626. #include "SamplePartStubs.c"
  4627.  
  4628.  
  4629.